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  int reverse=0);
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  int reverse=0);
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  int reverse=0);
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  int reverse=0);
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  // TODO add a reverse option
925 
926  enum applyType { BEFORE=1, EQUAL=2, AFTER=4, BEFORE_EQUAL=4, AFTER_EQUAL=6};
927  void xform(const UT_XformOrder &order,
928  applyType type, char limit,
929  T tx, T ty, T tz,
930  T rx, T ry, T rz,
931  T sx, T sy, T sz,
932  T px, T py, T pz);
933 
934  void rotate(const UT_XformOrder &order,
935  applyType type, char limit,
936  T rx, T ry, T rz);
937 
938  // extract only the translates from the matrix;
939  template <typename S>
940  inline void getTranslates(UT_Vector3T<S> &translates) const;
941  template <typename S>
942  inline void setTranslates(const UT_Vector3T<S> &translates);
943 
944  // This is a super-crack that returns the translation, scale, and radian
945  // rotation vectors given a transformation order and a valid xform matrix.
946  // It returns 0 if succesful, and non-zero otherwise: 1 if the embedded
947  // rotation matrix is invalid, 2 if the rotation order is invalid,
948  // and 3 for other problems. If any of the scaling values is 0, the method
949  // returns all zeroes, and a 0 return value.
950  template <typename S>
951  int explodeT(const UT_XformOrder &order,
953  UT_Vector3T<S> *shears) const;
956  UT_Vector3F *shears = 0) const
957  { return explodeT(order, r, s, t, shears); }
960  UT_Vector3D *shears = 0) const
961  { return explodeT(order, r, s, t, shears); }
962 
963  // This version of explode returns the t, r, and s, given a pivot value.
964  template <typename S>
965  int explodeT(const UT_XformOrder &order,
967  UT_Vector3T<S> &t, const UT_Vector3T<S> &p,
968  UT_Vector3T<S> *shears) const;
971  UT_Vector3F &t, const UT_Vector3F &p,
972  UT_Vector3F *shears = 0) const
973  { return explodeT(order, r, s, t, p, shears); }
976  UT_Vector3D &t, const UT_Vector3D &p,
977  UT_Vector3D *shears = 0) const
978  { return explodeT(order, r, s, t, p, shears); }
979 
980  // This version of explode returns the t, r, and s, given a PivotSpace.
981  template <typename S>
982  int explodeT(const UT_XformOrder &order,
984  UT_Vector3T<S> &t, const PivotSpaceT<S> &p,
985  UT_Vector3T<S> *shears) const;
988  UT_Vector3F &t, const PivotSpaceT<fpreal32> &p,
989  UT_Vector3F *shears = 0) const
990  { return explodeT(order, r, s, t, p, shears); }
993  UT_Vector3D &t, const PivotSpaceT<fpreal64> &p,
994  UT_Vector3D *shears = 0) const
995  { return explodeT(order, r, s, t, p, shears); }
996 
997 
998  // These versions treat the matrix as only containing a 2D
999  // transformation, that is in x, y, with a rotate around z.
1000  template <typename S>
1001  int explode2D(const UT_XformOrder &order,
1003  S *shears = 0) const;
1004 
1005  template <typename S>
1006  int explode2D(const UT_XformOrder &order,
1007  S &r, UT_Vector2T<S> &s,
1008  UT_Vector2T<S> &t, const UT_Vector2T<S> &p,
1009  S *shears = 0) const;
1010 
1011  /// WARNING: This may not produce good results! Instead, get the
1012  /// UT_Matrix3 part and call UT_Matrix3T::makeRotationMatrix().
1013  template <typename S>
1014  void extractRotate(UT_Matrix3T<S> &dst) const;
1015 
1016  /// Extract the translate, rotation (in radians), and stretch
1017  /// components of the 4x4 matrix, preferably using polar decomposition.
1018  /// This method is slower than alternatives (explode, crack), but provides
1019  /// better results for animation.
1020  /// @returns true if the polar decomposition succeeded, false otherwise
1021  /// Regardless of the return value, sensible values for translation
1022  /// rotation and stretch are computed.
1023  template <typename S>
1024  bool decompose(const UT_XformOrder &order,
1025  UT_Vector3T<S> &trn,
1027  UT_Matrix3T<T> &stretch,
1028  const int max_iter = 64,
1029  const T rel_tol = FLT_EPSILON) const;
1030 
1031  /// Composes a transform matrix given the translation, rotation (in
1032  /// radians), and stretch matrix components. This is the inverse of the
1033  /// decompose method.
1034  template <typename S>
1035  void compose(const UT_XformOrder &order,
1036  UT_Vector3T<S> &trn,
1038  UT_Matrix3T<T> &stretch);
1039 
1040  /// Perform the polar decomposition of the 3x3 matrix M into an orthogonal
1041  /// matrix Q and an symmetric positive-semidefinite matrix S. This is more
1042  /// useful than explode() or extractRotate() when the desire is to blend
1043  /// transforms. By default, it gives M=SQ, a left polar decomposition. If
1044  /// reverse is false, then it gives M=QS, a right polar decomposition.
1045  ///
1046  /// This method is similar to the UT_Matrix3 version except it only
1047  /// operates on the upper-right 3x3 portion.
1048  ///
1049  /// @pre The upper-right 3x3 portion of *this is non-singular
1050  /// @post The upper-right 3x3 porition = Q,
1051  /// and if stretch != 0: *stretch = S.
1052  /// @return True if successful
1053  bool polarDecompose(
1054  UT_Matrix3T<T> *stretch = nullptr,
1055  bool reverse = true,
1056  const int max_iter = 64,
1057  const T rel_tol = FLT_EPSILON);
1058 
1059  /// Turn this matrix into the "closest" rigid transformation
1060  /// (only rotations and translations) matrix.
1061  ///
1062  /// It uses polarDecompose and then negates the matrix if
1063  /// there is a negative determinant (scale). It returns false iff
1064  /// polarDecompose failed, possibly due to a singular matrix.
1065  ///
1066  /// This is currently the one true way to turn an arbitrary
1067  /// matrix4 into a rotation and translation matrix. If that
1068  /// ever changes, put a warning here, and you may want to update
1069  /// UT_Matrix3::makeRotationMatrix too.
1070  bool makeRigidMatrix(
1071  UT_Matrix3T<T> *stretch = nullptr,
1072  bool reverse = true,
1073  const int max_iter = 64,
1074  const T rel_tol = FLT_EPSILON);
1075 
1076  // Right multiply this matrix by a 3x3 matrix which scales by a given
1077  // amount along the direction of vector v. When applied to a vector w,
1078  // the stretched matrix (*this) stretches w in v by the amount given.
1079  // If norm is non-zero, v will be normalized prior to the operation.
1080  template <typename S>
1081  void stretch(UT_Vector3T<S> &v, T amount, int norm=1);
1082 
1083  T dot(unsigned i, unsigned j) const
1084  {
1085  return (i <= 3 && j <= 3) ?
1086  matx[i][0]*matx[j][0] + matx[i][1]*matx[j][1] +
1087  matx[i][2]*matx[j][2] + matx[i][3]*matx[j][3] : (T)0;
1088  }
1089 
1090  // Matrix += b * v1 * v2T
1091  template <typename S>
1092  void outerproductUpdate(T b,
1093  const UT_Vector4T<S> &v1, const UT_Vector4T<S> &v2);
1094 
1095  /// Create a reflection matrix for the given normal to the mirror plane.
1096  /// @{
1097  template <typename S>
1098  static UT_Matrix4T<T> reflectMat(const UT_Vector3T<S> &plane_origin,
1099  const UT_Vector3T<S> &plane_normal)
1100  {
1101  UT_Matrix4T<T> m(UT_Matrix3T<T>::reflectMat(plane_normal));
1102  m.pretranslate(-plane_origin);
1103  m.translate(plane_origin);
1104  return m;
1105  }
1106  /// @}
1107 
1108  // Sets the current matrix to a linear interpolation of the two homogenous
1109  // matrices given.
1110  void lerp(const UT_Matrix4T<T> &a, const UT_Matrix4T<T> &b, T t)
1111  {
1112  if (t == 0)
1113  *this = a;
1114  else if(t == 1)
1115  *this = b;
1116  else
1117  {
1118  for (size_t i = 0; i < tuple_size; i++)
1119  myFloats[i] = SYSlerp(a.myFloats[i], b.myFloats[i], t);
1120  }
1121  }
1122 
1123  /// Set the matrix to identity
1124  void identity() { *this = 1; }
1125  /// Set the matrix to zero
1126  void zero() { *this = 0; }
1127 
1128  bool isIdentity() const
1129  {
1130  // NB: DO NOT USE TOLERANCES!
1131  return(
1132  matx[0][0]==1 && matx[0][1]==0 &&
1133  matx[0][2]==0 && matx[0][3]==0 &&
1134  matx[1][0]==0 && matx[1][1]==1 &&
1135  matx[1][2]==0 && matx[1][3]==0 &&
1136  matx[2][0]==0 && matx[2][1]==0 &&
1137  matx[2][2]==1 && matx[2][3]==0 &&
1138  matx[3][0]==0 && matx[3][1]==0 &&
1139  matx[3][2]==0 && matx[3][3]==1);
1140  }
1141 
1142  bool isZero() const
1143  {
1144  // NB: DO NOT USE TOLERANCES!
1145  return(
1146  matx[0][0]==0 && matx[0][1]==0 &&
1147  matx[0][2]==0 && matx[0][3]==0 &&
1148  matx[1][0]==0 && matx[1][1]==0 &&
1149  matx[1][2]==0 && matx[1][3]==0 &&
1150  matx[2][0]==0 && matx[2][1]==0 &&
1151  matx[2][2]==0 && matx[2][3]==0 &&
1152  matx[3][0]==0 && matx[3][1]==0 &&
1153  matx[3][2]==0 && matx[3][3]==0);
1154  }
1155 
1156 
1157  /// Return the raw matrix data.
1158  // @{
1159  const T *data() const { return myFloats; }
1160  T *data() { return myFloats; }
1161  // @}
1162 
1163  /// Compute a hash
1164  unsigned hash() const { return SYSvector_hash(data(), tuple_size); }
1165 
1166  /// Return a matrix entry. No bounds checking on subscripts.
1167  // @{
1169  T &operator()(unsigned row, unsigned col)
1170  {
1171  UT_ASSERT_P(row < 4 && col < 4);
1172  return matx[row][col];
1173  }
1175  T operator()(unsigned row, unsigned col) const
1176  {
1177  UT_ASSERT_P(row < 4 && col < 4);
1178  return matx[row][col];
1179  }
1180  // @}
1181 
1182  /// Return a matrix row. No bounds checking on subscript.
1183  // @{
1185  T *operator()(unsigned row)
1186  {
1187  UT_ASSERT_P(row < 4);
1188  return matx[row];
1189  }
1191  const T *operator()(unsigned row) const
1192  {
1193  UT_ASSERT_P(row < 4);
1194  return matx[row];
1195  }
1196  inline
1197  const UT_Vector4T<T> &operator[](unsigned row) const;
1198  inline
1199  UT_Vector4T<T> &operator[](unsigned row);
1200  // @}
1201 
1202  /// Dot product with another matrix
1203  /// Does dot(a,b) = sum_ij a_ij * b_ij
1204  T dot(const UT_Matrix4T<T> &m) const;
1205 
1206  /// Euclidean or Frobenius norm of a matrix.
1207  /// Does sqrt(sum(a_ij ^2))
1209  { return SYSsqrt(getEuclideanNorm2()); }
1210  /// Euclidean norm squared.
1211  T getEuclideanNorm2() const;
1212 
1213  /// Get the 1-norm of this matrix, assuming a row vector convention.
1214  /// Returns the maximum absolute row sum. ie. max_i(sum_j(abs(a_ij)))
1215  T getNorm1() const;
1216 
1217  /// Get the inf-norm of this matrix, assuming a row vector convention.
1218  /// Returns the maximum absolute column sum. ie. max_j(sum_i(abs(a_ij)))
1219  T getNormInf() const;
1220 
1221  /// Get the max-norm of this matrix
1222  /// Returns the maximum absolute entry. ie. max_j(max_i(abs(a_ij)))
1223  T getNormMax() const;
1224 
1225  /// Get the spectral norm of this matrix
1226  /// Returns the maximum singular value.
1227  T getNormSpectral() const;
1228 
1229  /// L-Infinity Norm, but using col vector convention.
1230  SYS_DEPRECATED_REPLACE(19.0, "getNorm1")
1231  T getInfinityNorm() const { return getNormInf(); }
1232 
1233  /// Compute the exponential of A using Pade approximants with scaling and squaring by q
1234  UT_Matrix4T<T> &exp(int q);
1235 
1236  /// Compute the log of A using Taylor approximation
1237  UT_Matrix4T<T> &log(T tolerance = T(SYS_FTOLERANCE), int max_iterations = 10);
1238 
1239  /// Compute the square root of A
1240  UT_Matrix4T<T> &sqrt(T tolerance = T(SYS_FTOLERANCE), int max_iterations = 10);
1241 
1242  // I/O methods. Return 0 if read/write successful, -1 if unsuccessful.
1243  int save(std::ostream &os, int binary) const;
1244  bool load(UT_IStream &is);
1245  void dump(const char *msg="") const;
1246 
1247  void outAsciiNoName(std::ostream &os) const;
1248 
1249  /// @{
1250  /// Methods to serialize to a JSON stream. The matrix is stored as an
1251  /// array of 16 reals.
1252  bool save(UT_JSONWriter &w) const;
1253  bool save(UT_JSONValue &v) const;
1254  bool load(UT_JSONParser &p);
1255  /// @}
1256 
1257  static const UT_Matrix4T<T> &getIdentityMatrix();
1258 
1259  // I/O friends:
1260  friend std::ostream &operator<<(std::ostream &os, const UT_Matrix4T<T> &v)
1261  {
1262  v.writeClassName(os);
1263  v.outAsciiNoName(os);
1264  return os;
1265  }
1266 
1267  /// Returns the vector size
1268  static int entries() { return tuple_size; }
1269 
1270 
1271  // The matrix data:
1272  union {
1273  T matx[4][4];
1274  T myFloats[tuple_size];
1275  };
1276 
1277  /// Create a perspective projection matrix with the given parameters.
1278  /// This can be used to project points onto the so-called NDC coordinates
1279  /// of a camera. For example, given a point @c P (in the space of a
1280  /// camera):
1281  /// @code
1282  /// UT_Vector3 ndc;
1283  /// UT_Matrix4R proj;
1284  /// proj.perspective(zoom, image_aspect);
1285  /// ndc = P * proj;
1286  /// @endcode
1287  ///
1288  /// - @c zoom @n The zoom for the lens
1289  /// - @c image_aspect @n The aspect ratio of the image
1290  /// - @c pixel_aspect @n The pixel aspect (the aspect ratio of pixels)
1291  /// - @c near,far @n The near/far clipping planes
1292  /// - @c window @n The offset for the projection window.
1293  ///
1294  /// The projection transform will transform the z coordinate of the camera
1295  /// space point such that the near coordinate will map to 0 and the far
1296  /// coordinate will map to 1.
1297  /// That is <tt>n dz.z = fit(P.z, near, far, 0, 1); </tt>.
1298  /// Thus, if the near/far are set to 0/1, the NDC z-coordinate will
1299  /// be the same as the camera space z. If the near/far are set to 0/-1,
1300  /// the Z coordinate will be negated.
1301  ///
1302  /// @note Sometimes the @c zoom is expressed in terms of @c focal and @c
1303  /// aperture. In this case: <tt> zoom = focal/aperture </tt>
1304  /// @note Sometimes the @c image_aspect is expressed in terms of @c xres
1305  /// and @c yres. In this case: <tt> image_aspect = xres / yres </tt>
1306  /// @note To make a single transform from world space to NDC space given a
1307  /// camera matrix and a projection matrix, you would use
1308  /// <tt> worldToNDC = worldToCamera * projection; </tt>
1309  ///
1310  void perspective(fpreal zoom,
1311  fpreal image_aspect,
1312  fpreal pixel_aspect=1,
1313  fpreal clip_near=0, fpreal clip_far=1,
1314  fpreal window_xmin=0, fpreal window_xmax=1,
1315  fpreal window_ymin=0, fpreal window_ymax=1);
1316  /// Create an orthographic projection matrix with the given parameters.
1317  /// This can be used to project points onto the so-called NDC coordinates
1318  /// of a camera. For example, given a point @c P (in the space of a
1319  /// camera):
1320  /// @code
1321  /// UT_Vector3 ndc;
1322  /// UT_Matrix4R proj;
1323  /// proj.orthographic(zoom, 1, image_aspect);
1324  /// ndc = P * proj;
1325  /// @endcode
1326  ///
1327  /// - @c zoom @n The zoom for the lens
1328  /// - @c orthowidth @n An additional "zoom" factor
1329  /// - @c image_aspect @n The resolution of the image
1330  /// - @c pixel_aspect @n The pixel aspect (the aspect ratio of pixels)
1331  /// - @c near,far @n The near/far clipping planes
1332  /// - @c window @n The offset for the projection window.
1333  ///
1334  /// The projection transform will transform the z coordinate of the camera
1335  /// space point such that the near coordinate will map to 0 and the far
1336  /// coordinate will map to 1.
1337  /// That is <tt>n dz.z = fit(P.z, near, far, 0, 1); </tt>.
1338  /// Thus, if the near/far are set to 0/1, the NDC z-coordinate will
1339  /// be the same as the camera space z. If the near/far are set to 0/-1,
1340  /// the Z coordinate will be negated.
1341  ///
1342  /// @note Sometimes the @c zoom is expressed in terms of @c focal and @c
1343  /// aperture. In this case: <tt> zoom = focal/aperture </tt>
1344  /// @note Sometimes the @c image_aspect is expressed in terms of @c xrex
1345  /// and @c yres. In this case: <tt> image_aspect = xres / yres </tt>
1346  /// @note To make a single transform from world space to NDC space given a
1347  /// camera matrix and a projection matrix, you would use
1348  /// <tt> worldToNDC = worldToCamera * projection; </tt>
1349  ///
1350  void orthographic(fpreal zoom,
1351  fpreal orthowidth,
1352  fpreal image_aspect,
1353  fpreal pixel_aspect=1,
1354  fpreal clip_near=0, fpreal clip_far=1,
1355  fpreal window_xmin=0, fpreal window_xmax=1,
1356  fpreal window_ymin=0, fpreal window_ymax=1);
1357 
1358  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
1359  /// order given by a templated UT_XformOrder.
1360  template <int ORDER>
1361  void rotate(T rx, T ry, T rz);
1362 
1363 private:
1364  // Operation to aid in cofactor computation
1366  void coVals(int k, int r[3]) const
1367  {
1368  switch (k)
1369  {
1370  case 0: r[0] = 1; r[1] = 2; r[2] = 3; break;
1371  case 1: r[0] = 0; r[1] = 2; r[2] = 3; break;
1372  case 2: r[0] = 0; r[1] = 1; r[2] = 3; break;
1373  case 3: r[0] = 0; r[1] = 1; r[2] = 2; break;
1374  }
1375  }
1376 
1377  static UT_Matrix4T<T> theIdentityMatrix;
1378 
1379  void writeClassName(std::ostream &os) const;
1380  static const char *className();
1381 };
1382 
1383 // Vector4 operators:
1384 
1385 template <typename T>
1386 template <typename S>
1387 inline
1389 {
1390  matx[0][0] = matx[0][1] = matx[0][2] = matx[0][3] = vec.x();
1391  matx[1][0] = matx[1][1] = matx[1][2] = matx[1][3] = vec.y();
1392  matx[2][0] = matx[2][1] = matx[2][2] = matx[2][3] = vec.z();
1393  matx[3][0] = matx[3][1] = matx[3][2] = matx[3][3] = vec.w();
1394  return *this;
1395 }
1396 
1397 template <typename T>
1398 template <typename S>
1399 inline
1401 {
1402  T x = vec.x(); T y = vec.y();
1403  T z = vec.z(); T w = vec.w();
1404  matx[0][0]+=x; matx[0][1]+=x; matx[0][2]+=x; matx[0][3]+=x;
1405  matx[1][0]+=y; matx[1][1]+=y; matx[1][2]+=y; matx[1][3]+=y;
1406  matx[2][0]+=z; matx[2][1]+=z; matx[2][2]+=z; matx[2][3]+=z;
1407  matx[3][0]+=w; matx[3][1]+=w; matx[3][2]+=w; matx[3][3]+=w;
1408  return *this;
1409 }
1410 
1411 template <typename T>
1412 template <typename S>
1413 inline
1415 {
1416  T x = vec.x(); T y = vec.y();
1417  T z = vec.z(); T w = vec.w();
1418  matx[0][0]-=x; matx[0][1]-=x; matx[0][2]-=x; matx[0][3]-=x;
1419  matx[1][0]-=y; matx[1][1]-=y; matx[1][2]-=y; matx[1][3]-=y;
1420  matx[2][0]-=z; matx[2][1]-=z; matx[2][2]-=z; matx[2][3]-=z;
1421  matx[3][0]-=w; matx[3][1]-=w; matx[3][2]-=w; matx[3][3]-=w;
1422  return *this;
1423 }
1424 
1425 template <typename T>
1426 template <typename S>
1427 inline
1429 {
1430  translates.x() = matx[3][0];
1431  translates.y() = matx[3][1];
1432  translates.z() = matx[3][2];
1433 }
1434 
1435 template <typename T>
1436 template <typename S>
1437 inline
1439 {
1440  matx[3][0] = translates.x();
1441  matx[3][1] = translates.y();
1442  matx[3][2] = translates.z();
1443 }
1444 
1445 template <typename T>
1446 inline
1448 {
1449  UT_ASSERT_P(row < 4);
1450  return *(const UT_Vector4T<T>*)(matx[row]);
1451 }
1452 
1453 template <typename T>
1454 inline
1456 {
1457  UT_ASSERT_P(row < 4);
1458  return *(UT_Vector4T<T>*)(matx[row]);
1459 }
1460 
1461 template <typename T>
1462 template <typename S>
1463 inline UT_Matrix4T<T> &
1465 {
1466  T a, b, c, d;
1467  a = matx[0][0]; b = matx[0][1]; c = matx[0][2]; d = matx[0][3];
1468  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1469  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1470  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1471  matx[0][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1472 
1473  a = matx[1][0]; b = matx[1][1]; c = matx[1][2]; d = matx[1][3];
1474  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1475  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1476  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1477  matx[1][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1478 
1479  a = matx[2][0]; b = matx[2][1]; c = matx[2][2]; d = matx[2][3];
1480  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1481  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1482  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1483  matx[2][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1484 
1485  a = matx[3][0]; b = matx[3][1]; c = matx[3][2]; d = matx[3][3];
1486  matx[3][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1487  matx[3][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1488  matx[3][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1489  matx[3][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1490  return *this;
1491 }
1492 
1493 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1494 template <>
1495 template <>
1496 inline UT_Matrix4T<float> &
1498 {
1499  // rows of right matrix
1500  const v4uf m0(m.matx[0]);
1501  const v4uf m1(m.matx[1]);
1502  const v4uf m2(m.matx[2]);
1503  const v4uf m3(m.matx[3]);
1504 
1505  v4uf row;
1506 
1507  for (int i = 0; i < 4; i++)
1508  {
1509  row = m0 * v4uf(matx[i][0]);
1510  row += m1 * v4uf(matx[i][1]);
1511  row += m2 * v4uf(matx[i][2]);
1512  row += m3 * v4uf(matx[i][3]);
1513 
1514  VM_STORE(matx[i], row.vector);
1515  }
1516  return *this;
1517 }
1518 #endif
1519 
1520 template <typename T>
1521 template <typename S>
1522 inline UT_Matrix4T<T> &
1524 {
1525  T a, b, c;
1526  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
1527  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1528  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1529  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1530 
1531  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
1532  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1533  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1534  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1535 
1536  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
1537  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1538  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1539  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1540 
1541  a = matx[3][0]; b = matx[3][1]; c = matx[3][2];
1542  matx[3][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1543  matx[3][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1544  matx[3][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1545  return *this;
1546 }
1547 
1548 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1549 #include "UT_Matrix3.h"
1550 template <>
1551 template <>
1552 inline UT_Matrix4T<float> &
1554 {
1555  const v4uf m0(m(0));
1556  const v4uf m1(m(1));
1557  const v4uf m2(m(2,0), m(2,1), m(2,2), 0);
1558 
1559  for (int i = 0; i < 4; ++i)
1560  {
1561  // Load ith row of this matrix
1562  v4uf row = m0 * v4uf(matx[i][0]);
1563  row += m1 * v4uf(matx[i][1]);
1564  row += m2 * v4uf(matx[i][2]);
1565 
1566  const float last = matx[i][3];
1567  vm_store(matx[i], row.vector);
1568  matx[i][3] = last;
1569  }
1570  return *this;
1571 }
1572 template <> inline void
1574 {
1575  // Lerp row by row
1576  for (int i = 0; i < 4; ++i) // Should unroll this
1577  {
1578  const v4uf ar(a.matx[i]);
1579  const v4uf br(b.matx[i]);
1580  const v4uf cr = SYSlerp(ar, br, t);
1581  vm_store(matx[i], cr.vector);
1582  }
1583 }
1584 #endif
1585 
1586 
1587 template <typename T>
1588 inline void
1590 {
1591  T a, b, c, d;
1592  a = matx[0][0]; b = matx[1][0]; c = matx[2][0]; d = matx[3][0];
1593  matx[0][0] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1594  matx[1][0] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1595  matx[2][0] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1596  matx[3][0] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1597 
1598  a = matx[0][1]; b = matx[1][1]; c = matx[2][1]; d = matx[3][1];
1599  matx[0][1] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1600  matx[1][1] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1601  matx[2][1] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1602  matx[3][1] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1603 
1604  a = matx[0][2]; b = matx[1][2]; c = matx[2][2]; d = matx[3][2];
1605  matx[0][2] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1606  matx[1][2] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1607  matx[2][2] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1608  matx[3][2] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1609 
1610  a = matx[0][3]; b = matx[1][3]; c = matx[2][3]; d = matx[3][3];
1611  matx[0][3] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1612  matx[1][3] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1613  matx[2][3] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1614  matx[3][3] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1615 }
1616 
1617 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1618 template <>
1619 inline void
1621 {
1622  const v4uf m0(matx[0]);
1623  const v4uf m1(matx[1]);
1624  const v4uf m2(matx[2]);
1625  const v4uf m3(matx[3]);
1626 
1627  for (int i = 0; i < 4; ++i)
1628  {
1629  const v4uf row = m0 * v4uf(m.matx[i][0])
1630  + m1 * v4uf(m.matx[i][1])
1631  + m2 * v4uf(m.matx[i][2])
1632  + m3 * v4uf(m.matx[i][3]);
1633 
1634  VM_STORE(matx[i], row.vector);
1635  }
1636 }
1637 #endif
1638 
1639 // Free floating functions:
1640 template <typename T>
1641 inline UT_Matrix4T<T>
1643 {
1644  T m[4][4];
1645  m[0][0] = m1(0,0)+m2(0,0); m[0][1] = m1(0,1)+m2(0,1);
1646  m[0][2] = m1(0,2)+m2(0,2); m[0][3] = m1(0,3)+m2(0,3);
1647 
1648  m[1][0] = m1(1,0)+m2(1,0); m[1][1] = m1(1,1)+m2(1,1);
1649  m[1][2] = m1(1,2)+m2(1,2); m[1][3] = m1(1,3)+m2(1,3);
1650 
1651  m[2][0] = m1(2,0)+m2(2,0); m[2][1] = m1(2,1)+m2(2,1);
1652  m[2][2] = m1(2,2)+m2(2,2); m[2][3] = m1(2,3)+m2(2,3);
1653 
1654  m[3][0] = m1(3,0)+m2(3,0); m[3][1] = m1(3,1)+m2(3,1);
1655  m[3][2] = m1(3,2)+m2(3,2); m[3][3] = m1(3,3)+m2(3,3);
1656  return UT_Matrix4T<T>(m);
1657 }
1658 template <typename T>
1659 inline UT_Matrix4T<T>
1661 {
1662  T m[4][4];
1663  m[0][0] = m1(0,0)-m2(0,0); m[0][1] = m1(0,1)-m2(0,1);
1664  m[0][2] = m1(0,2)-m2(0,2); m[0][3] = m1(0,3)-m2(0,3);
1665 
1666  m[1][0] = m1(1,0)-m2(1,0); m[1][1] = m1(1,1)-m2(1,1);
1667  m[1][2] = m1(1,2)-m2(1,2); m[1][3] = m1(1,3)-m2(1,3);
1668 
1669  m[2][0] = m1(2,0)-m2(2,0); m[2][1] = m1(2,1)-m2(2,1);
1670  m[2][2] = m1(2,2)-m2(2,2); m[2][3] = m1(2,3)-m2(2,3);
1671 
1672  m[3][0] = m1(3,0)-m2(3,0); m[3][1] = m1(3,1)-m2(3,1);
1673  m[3][2] = m1(3,2)-m2(3,2); m[3][3] = m1(3,3)-m2(3,3);
1674  return UT_Matrix4T<T>(m);
1675 }
1676 template <typename T>
1677 inline UT_Matrix4T<T>
1679 {
1680  T m[4][4];
1681  m[0][0] = m1(0,0)*m2(0,0) + m1(0,1)*m2(1,0) +
1682  m1(0,2)*m2(2,0) + m1(0,3)*m2(3,0) ;
1683  m[0][1] = m1(0,0)*m2(0,1) + m1(0,1)*m2(1,1) +
1684  m1(0,2)*m2(2,1) + m1(0,3)*m2(3,1) ;
1685  m[0][2] = m1(0,0)*m2(0,2) + m1(0,1)*m2(1,2) +
1686  m1(0,2)*m2(2,2) + m1(0,3)*m2(3,2) ;
1687  m[0][3] = m1(0,0)*m2(0,3) + m1(0,1)*m2(1,3) +
1688  m1(0,2)*m2(2,3) + m1(0,3)*m2(3,3) ;
1689 
1690  m[1][0] = m1(1,0)*m2(0,0) + m1(1,1)*m2(1,0) +
1691  m1(1,2)*m2(2,0) + m1(1,3)*m2(3,0) ;
1692  m[1][1] = m1(1,0)*m2(0,1) + m1(1,1)*m2(1,1) +
1693  m1(1,2)*m2(2,1) + m1(1,3)*m2(3,1) ;
1694  m[1][2] = m1(1,0)*m2(0,2) + m1(1,1)*m2(1,2) +
1695  m1(1,2)*m2(2,2) + m1(1,3)*m2(3,2) ;
1696  m[1][3] = m1(1,0)*m2(0,3) + m1(1,1)*m2(1,3) +
1697  m1(1,2)*m2(2,3) + m1(1,3)*m2(3,3) ;
1698 
1699  m[2][0] = m1(2,0)*m2(0,0) + m1(2,1)*m2(1,0) +
1700  m1(2,2)*m2(2,0) + m1(2,3)*m2(3,0) ;
1701  m[2][1] = m1(2,0)*m2(0,1) + m1(2,1)*m2(1,1) +
1702  m1(2,2)*m2(2,1) + m1(2,3)*m2(3,1) ;
1703  m[2][2] = m1(2,0)*m2(0,2) + m1(2,1)*m2(1,2) +
1704  m1(2,2)*m2(2,2) + m1(2,3)*m2(3,2) ;
1705  m[2][3] = m1(2,0)*m2(0,3) + m1(2,1)*m2(1,3) +
1706  m1(2,2)*m2(2,3) + m1(2,3)*m2(3,3) ;
1707 
1708  m[3][0] = m1(3,0)*m2(0,0) + m1(3,1)*m2(1,0) +
1709  m1(3,2)*m2(2,0) + m1(3,3)*m2(3,0) ;
1710  m[3][1] = m1(3,0)*m2(0,1) + m1(3,1)*m2(1,1) +
1711  m1(3,2)*m2(2,1) + m1(3,3)*m2(3,1) ;
1712  m[3][2] = m1(3,0)*m2(0,2) + m1(3,1)*m2(1,2) +
1713  m1(3,2)*m2(2,2) + m1(3,3)*m2(3,2) ;
1714  m[3][3] = m1(3,0)*m2(0,3) + m1(3,1)*m2(1,3) +
1715  m1(3,2)*m2(2,3) + m1(3,3)*m2(3,3) ;
1716  return UT_Matrix4T<T>(m);
1717 }
1718 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1719 template <>
1720 inline UT_Matrix4T<float>
1722 {
1724 
1725  const v4uf r0(m2.matx[0]);
1726  const v4uf r1(m2.matx[1]);
1727  const v4uf r2(m2.matx[2]);
1728  const v4uf r3(m2.matx[3]);
1729 
1730  for (int i = 0; i < 4; ++i)
1731  {
1732  const v4uf row = r0 * v4uf(m1.matx[i][0])
1733  + r1 * v4uf(m1.matx[i][1])
1734  + r2 * v4uf(m1.matx[i][2])
1735  + r3 * v4uf(m1.matx[i][3]);
1736 
1737  VM_STORE(result.matx[i], row.vector);
1738  }
1739  return result;
1740 }
1741 #endif
1742 
1743 template <typename T, typename S>
1744 inline UT_Matrix4T<T>
1746 {
1747  T m[4][4];
1748  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1749  m[0][0] = m1(0,0) + x; m[0][1] = m1(0,1) + x;
1750  m[0][2] = m1(0,2) + x; m[0][3] = m1(0,3) + x;
1751 
1752  m[1][0] = m1(1,0) + y; m[1][1] = m1(1,1) + y;
1753  m[1][2] = m1(1,2) + y; m[1][3] = m1(1,3) + y;
1754 
1755  m[2][0] = m1(2,0) + z; m[2][1] = m1(2,1) + z;
1756  m[2][2] = m1(2,2) + z; m[2][3] = m1(2,3) + z;
1757 
1758  m[3][0] = m1(3,0) + w; m[3][1] = m1(3,1) + w;
1759  m[3][2] = m1(3,2) + w; m[3][3] = m1(3,3) + w;
1760  return UT_Matrix4T<T>(m);
1761 }
1762 
1763 template <typename T, typename S>
1764 inline UT_Matrix4T<T>
1765 operator+(const UT_Vector4T<S> &vec, const UT_Matrix4T<T> &mat)
1766 {
1767  return mat+vec;
1768 }
1769 
1770 template <typename T, typename S>
1771 inline UT_Matrix4T<T>
1773 {
1774  T m[4][4];
1775  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1776  m[0][0] = m1(0,0) - x; m[0][1] = m1(0,1) - x;
1777  m[0][2] = m1(0,2) - x; m[0][3] = m1(0,3) - x;
1778 
1779  m[1][0] = m1(1,0) - y; m[1][1] = m1(1,1) - y;
1780  m[1][2] = m1(1,2) - y; m[1][3] = m1(1,3) - y;
1781 
1782  m[2][0] = m1(2,0) - z; m[2][1] = m1(2,1) - z;
1783  m[2][2] = m1(2,2) - z; m[2][3] = m1(2,3) - z;
1784 
1785  m[3][0] = m1(3,0) - w; m[3][1] = m1(3,1) - w;
1786  m[3][2] = m1(3,2) - w; m[3][3] = m1(3,3) - w;
1787  return UT_Matrix4T<T>(m);
1788 }
1789 
1790 template <typename T, typename S>
1791 inline UT_Matrix4T<T>
1793 {
1794  T m[4][4];
1795  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1796  m[0][0] = x - m1(0,0); m[0][1] = x - m1(0,1);
1797  m[0][2] = x - m1(0,2); m[0][3] = x - m1(0,3);
1798 
1799  m[1][0] = y - m1(1,0); m[1][1] = y - m1(1,1);
1800  m[1][2] = y - m1(1,2); m[1][3] = y - m1(1,3);
1801 
1802  m[2][0] = z - m1(2,0); m[2][1] = z - m1(2,1);
1803  m[2][2] = z - m1(2,2); m[2][3] = z - m1(2,3);
1804 
1805  m[3][0] = w - m1(3,0); m[3][1] = w - m1(3,1);
1806  m[3][2] = w - m1(3,2); m[3][3] = w - m1(3,3);
1807  return UT_Matrix4T<T>(m);
1808 }
1809 
1810 template <typename T, typename S>
1811 inline UT_Matrix4T<T>
1813 {
1814  T m[4][4];
1815  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;
1816  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;
1817  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;
1818  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;
1819  return UT_Matrix4T<T>(m);
1820 }
1821 
1822 template <typename T, typename S>
1823 inline UT_Matrix4T<T>
1825 {
1826  T m[4][4];
1827  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);
1828  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);
1829  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);
1830  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);
1831  return UT_Matrix4T<T>(m);
1832 }
1833 
1834 template <typename T, typename S>
1835 inline UT_Matrix4T<T>
1836 operator*(S sc, const UT_Matrix4T<T> &m1)
1837 {
1838  return m1*sc;
1839 }
1840 
1841 template <typename T, typename S>
1842 inline UT_Matrix4T<T>
1844 {
1845  T m[4][4];
1846  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;
1847  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;
1848  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;
1849  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;
1850  return UT_Matrix4T<T>(m);
1851 }
1852 
1853 template <typename T, typename S>
1854 inline
1856 operator/(const UT_Matrix4T<T> &m1, S scalar)
1857 {
1858  return (m1 * (T(1.0)/scalar));
1859 }
1860 
1861 template <typename T, typename S>
1862 inline UT_Matrix4T<T>
1864 {
1865  T m[4][4];
1866  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);
1867  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);
1868  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);
1869  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);
1870  return UT_Matrix4T<T>(m);
1871 }
1872 
1873 /// Multiplication of a row or column vector by a matrix (ie. right vs. left
1874 /// multiplication respectively). The operator*() declared above is an alias
1875 /// for rowVecMult(). The functions that take a 4x4 matrix first extend
1876 /// the vector to 4D (with a trailing 1.0 element).
1877 //
1878 // @{
1879 // Notes on optimisation of matrix/vector multiplies:
1880 // - multiply(dest, mat) functions have been deprecated in favour of
1881 // rowVecMult/colVecMult routines, which produce temporaries. For these to
1882 // offer comparable performance, the compiler has to optimize away the
1883 // temporary, but most modern compilers can do this. Performance tests with
1884 // gcc3.3 indicate that this is a realistic expectation for modern
1885 // compilers.
1886 // - since matrix/vector multiplies cannot be done without temporary data,
1887 // the "primary" functions are the global matrix/vector
1888 // rowVecMult/colVecMult routines, rather than the member functions.
1889 // - inlining is explicitly requested only for non-deprecated functions
1890 // involving the native types (UT_Vector3 and UT_Matrix3)
1891 
1892 template <typename T, typename S>
1893 inline UT_Vector3T<T> rowVecMult(const UT_Vector3T<T> &v, const UT_Matrix4T<S> &m);
1894 template <typename T, typename S>
1895 inline UT_Vector3T<T> colVecMult(const UT_Matrix4T<S> &m, const UT_Vector3T<T> &v);
1896 
1897 template <typename T, typename S>
1898 inline UT_Vector3T<T> rowVecMult3(const UT_Vector3T<T> &v, const UT_Matrix4T<S> &m);
1899 template <typename T, typename S>
1900 inline UT_Vector3T<T> colVecMult3(const UT_Matrix4T<S> &m, const UT_Vector3T<T> &v);
1901 // @}
1902 
1903 template <typename T, typename S>
1904 inline UT_Vector3T<T>
1906 {
1907  return UT_Vector3T<T>(
1908  v.x()*m(0,0) + v.y()*m(1,0) + v.z()*m(2,0) + m(3,0),
1909  v.x()*m(0,1) + v.y()*m(1,1) + v.z()*m(2,1) + m(3,1),
1910  v.x()*m(0,2) + v.y()*m(1,2) + v.z()*m(2,2) + m(3,2)
1911  );
1912 }
1913 template <typename T, typename S>
1914 inline UT_Vector3T<T>
1916 {
1917  return rowVecMult(v, m);
1918 }
1919 
1920 template <typename T, typename S>
1921 inline UT_Vector3T<T>
1923 {
1924  return UT_Vector3T<T>(
1925  v.x()*m(0,0) + v.y()*m(1,0) + v.z()*m(2,0),
1926  v.x()*m(0,1) + v.y()*m(1,1) + v.z()*m(2,1),
1927  v.x()*m(0,2) + v.y()*m(1,2) + v.z()*m(2,2)
1928  );
1929 }
1930 
1931 template <typename T, typename S>
1932 inline UT_Vector3T<T>
1934 {
1935  return UT_Vector3T<T>(
1936  v.x()*m(0,0) + v.y()*m(0,1) + v.z()*m(0,2) + m(0,3),
1937  v.x()*m(1,0) + v.y()*m(1,1) + v.z()*m(1,2) + m(1,3),
1938  v.x()*m(2,0) + v.y()*m(2,1) + v.z()*m(2,2) + m(2,3)
1939  );
1940 }
1941 
1942 template <typename T, typename S>
1943 inline UT_Vector3T<T>
1945 {
1946  return UT_Vector3T<T>(
1947  v.x()*m(0,0) + v.y()*m(0,1) + v.z()*m(0,2),
1948  v.x()*m(1,0) + v.y()*m(1,1) + v.z()*m(1,2),
1949  v.x()*m(2,0) + v.y()*m(2,1) + v.z()*m(2,2)
1950  );
1951 }
1952 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1953 template <>
1954 inline UT_Vector3T<float>
1956 {
1957  const v4uf result =
1958  v4uf(m.matx[0]) * v4uf(v[0])
1959  + v4uf(m.matx[1]) * v4uf(v[1])
1960  + v4uf(m.matx[2]) * v4uf(v[2])
1961  + v4uf(m.matx[3]); // * v[3] == 1.0
1962 
1963  // Requires v4uf to be contiguous in memory
1964  return UT_Vector3T<float>((float*) &result);
1965 }
1966 template <>
1967 inline UT_Vector3T<float>
1969 {
1970  const v4uf result =
1971  v4uf(m.matx[0]) * v4uf(v[0])
1972  + v4uf(m.matx[1]) * v4uf(v[1])
1973  + v4uf(m.matx[2]) * v4uf(v[2]);
1974 
1975  // Requires v4uf to be contiguous in memory
1976  return UT_Vector3T<float>((float*) &result);
1977 }
1978 template <>
1979 inline UT_Vector3T<float>
1981 {
1982  const v4uf result =
1983  v4uf(m(0,0), m(1,0), m(2,0), m(3,0)) * v4uf(v[0])
1984  + v4uf(m(0,1), m(1,1), m(2,1), m(3,1)) * v4uf(v[1])
1985  + v4uf(m(0,2), m(1,2), m(2,2), m(3,2)) * v4uf(v[2])
1986  + v4uf(m(0,3), m(1,3), m(2,3), m(3,3)); // * v[3] == 1.0
1987 
1988  // Requires v4uf to be contiguous in memory
1989  return UT_Vector3T<float>((float*) &result);
1990 }
1991 template <>
1992 inline UT_Vector3T<float>
1994 {
1995  const v4uf result =
1996  v4uf(m(0,0), m(1,0), m(2,0), m(3,0)) * v4uf(v[0])
1997  + v4uf(m(0,1), m(1,1), m(2,1), m(3,1)) * v4uf(v[1])
1998  + v4uf(m(0,2), m(1,2), m(2,2), m(3,2)) * v4uf(v[2]);
1999 
2000  // Requires v4uf to be contiguous in memory
2001  return UT_Vector3T<float>((float*) &result);
2002 }
2003 #endif
2004 
2005 
2006 template <typename T>
2007 SYS_FORCE_INLINE void
2009 {
2010  operator=(::rowVecMult(*this, m));
2011 }
2012 template <typename T>
2013 SYS_FORCE_INLINE void
2015 {
2016  operator=(::rowVecMult(*this, m));
2017 }
2018 template <typename T>
2019 SYS_FORCE_INLINE void
2021 {
2022  operator=(::colVecMult(m, *this));
2023 }
2024 template <typename T>
2025 SYS_FORCE_INLINE void
2027 {
2028  operator=(::colVecMult(m, *this));
2029 }
2030 template <typename T>
2031 SYS_FORCE_INLINE void
2033 {
2034  operator=(::rowVecMult3(*this, m));
2035 }
2036 template <typename T>
2037 SYS_FORCE_INLINE void
2039 {
2040  operator=(::rowVecMult3(*this, m));
2041 }
2042 template <typename T>
2043 SYS_FORCE_INLINE void
2045 {
2046  operator=(::colVecMult3(m, *this));
2047 }
2048 template <typename T>
2049 SYS_FORCE_INLINE void
2051 {
2052  operator=(::colVecMult3(m, *this));
2053 }
2054 template <typename T>
2055 template <typename S>
2058 {
2059  rowVecMult(m);
2060  return *this;
2061 }
2062 template <typename T>
2063 template <typename S>
2064 SYS_FORCE_INLINE void
2066 {
2067  rowVecMult3(mat);
2068 }
2069 template <typename T>
2070 template <typename S>
2071 SYS_FORCE_INLINE void
2073 {
2074  colVecMult3(mat);
2075 }
2076 template <typename T>
2077 template <typename S>
2078 SYS_FORCE_INLINE void
2080 {
2081  dest = ::rowVecMult3(*this, mat);
2082 }
2083 template <typename T>
2084 template <typename S>
2085 SYS_FORCE_INLINE void
2087 {
2088  dest = ::colVecMult3(mat, *this);
2089 }
2090 template <typename T>
2091 template <typename S>
2092 SYS_FORCE_INLINE void
2094 {
2095  dest = ::rowVecMult(*this, mat);
2096 }
2097 
2098 template <typename T>
2099 static inline
2100 T dot(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2){
2101  return m1.dot(m2);
2102 }
2103 
2104 template <typename T>
2105 inline
2107 {
2108  return UT_Matrix4T<T>(
2109  SYSmin(v1(0,0), v2(0,0)),
2110  SYSmin(v1(0,1), v2(0,1)),
2111  SYSmin(v1(0,2), v2(0,2)),
2112  SYSmin(v1(0,3), v2(0,3)),
2113  SYSmin(v1(1,0), v2(1,0)),
2114  SYSmin(v1(1,1), v2(1,1)),
2115  SYSmin(v1(1,2), v2(1,2)),
2116  SYSmin(v1(1,3), v2(1,3)),
2117  SYSmin(v1(2,0), v2(2,0)),
2118  SYSmin(v1(2,1), v2(2,1)),
2119  SYSmin(v1(2,2), v2(2,2)),
2120  SYSmin(v1(2,3), v2(2,3)),
2121  SYSmin(v1(3,0), v2(3,0)),
2122  SYSmin(v1(3,1), v2(3,1)),
2123  SYSmin(v1(3,2), v2(3,2)),
2124  SYSmin(v1(3,3), v2(3,3))
2125  );
2126 }
2127 
2128 template <typename T>
2129 inline
2131 {
2132  return UT_Matrix4T<T>(
2133  SYSmax(v1(0,0), v2(0,0)),
2134  SYSmax(v1(0,1), v2(0,1)),
2135  SYSmax(v1(0,2), v2(0,2)),
2136  SYSmax(v1(0,3), v2(0,3)),
2137  SYSmax(v1(1,0), v2(1,0)),
2138  SYSmax(v1(1,1), v2(1,1)),
2139  SYSmax(v1(1,2), v2(1,2)),
2140  SYSmax(v1(1,3), v2(1,3)),
2141  SYSmax(v1(2,0), v2(2,0)),
2142  SYSmax(v1(2,1), v2(2,1)),
2143  SYSmax(v1(2,2), v2(2,2)),
2144  SYSmax(v1(2,3), v2(2,3)),
2145  SYSmax(v1(3,0), v2(3,0)),
2146  SYSmax(v1(3,1), v2(3,1)),
2147  SYSmax(v1(3,2), v2(3,2)),
2148  SYSmax(v1(3,3), v2(3,3))
2149  );
2150 }
2151 
2152 template <typename T,typename S>
2153 inline
2155 {
2156  return UT_Matrix4T<T>(
2157  SYSlerp(v1(0,0), v2(0,0), t),
2158  SYSlerp(v1(0,1), v2(0,1), t),
2159  SYSlerp(v1(0,2), v2(0,2), t),
2160  SYSlerp(v1(0,3), v2(0,3), t),
2161  SYSlerp(v1(1,0), v2(1,0), t),
2162  SYSlerp(v1(1,1), v2(1,1), t),
2163  SYSlerp(v1(1,2), v2(1,2), t),
2164  SYSlerp(v1(1,3), v2(1,3), t),
2165  SYSlerp(v1(2,0), v2(2,0), t),
2166  SYSlerp(v1(2,1), v2(2,1), t),
2167  SYSlerp(v1(2,2), v2(2,2), t),
2168  SYSlerp(v1(2,3), v2(2,3), t),
2169  SYSlerp(v1(3,0), v2(3,0), t),
2170  SYSlerp(v1(3,1), v2(3,1), t),
2171  SYSlerp(v1(3,2), v2(3,2), t),
2172  SYSlerp(v1(3,3), v2(3,3), t)
2173  );
2174 }
2175 #ifndef UT_DISABLE_VECTORIZE_MATRIX
2176 template <>
2177 inline
2179 {
2181  for (int i = 0; i < 4; ++i)
2182  {
2183  const v4uf r1(v1.matx[i]);
2184  const v4uf r2(v2.matx[i]);
2185  const v4uf rr = SYSlerp(r1, r2, t);
2186  vm_store(result.matx[i], rr.vector);
2187  }
2188  return result;
2189 }
2190 #endif
2191 
2192 template< typename T, exint D >
2193 class UT_FixedVector;
2194 
2195 template<typename T>
2197 {
2199  typedef T DataType;
2200  static const exint TupleSize = 16;
2201  static const bool isVectorType = true;
2202 };
2203 
2204 // Overload for custom formatting of UT_Matrix4T<T> with UTformat.
2205 template<typename T>
2206 UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix4T<T> &v);
2207 
2208 
2209 // UT_Matrix4TFromUnbounded<T> is a function object that
2210 // creates a UT_Matrix4T<T> from an unbounded array-like type 'as'.
2211 // 'as' must have at size at least 16 = 4 * 4.
2212 template <typename T>
2214 {
2215  template< typename TS >
2216  constexpr SYS_FORCE_INLINE UT_Matrix4T<T> operator()(const TS& as) const noexcept
2217  {
2218  return UT_Matrix4T<T>{
2219  as[ 0], as[ 1], as[ 2], as[ 3],
2220  as[ 4], as[ 5], as[ 6], as[ 7],
2221  as[ 8], as[ 9], as[10], as[11],
2222  as[12], as[13], as[14], as[15]
2223  };
2224  }
2225 };
2226 
2227 // UT_FromUnbounded<V> creates a V from an unbounded array-like type
2228 
2229 // Primary
2230 template <typename V >
2231 struct UT_FromUnbounded;
2232 
2233 // Partial specialization for UT_Matrix4T
2234 template <typename T>
2236 
2237 
2238 // UT_Matrix4TFromFixed<T> is a function object that
2239 // creates a UT_Matrix4T<T> from a fixed array-like type TS,
2240 // examples of which include T[16], UT_FixedVector<T,16> and UT_FixedArray<T,16> (AKA std::array<T,16>)
2241 template <typename T>
2243 {
2244  template< typename TS >
2245  constexpr SYS_FORCE_INLINE UT_Matrix4T<T> operator()(const TS& as) const noexcept
2246  {
2247  SYS_STATIC_ASSERT( SYS_IsFixedArrayOf_v< TS, T, 4 * 4 > );
2248 
2249  return UT_Matrix4TFromUnbounded<T>{}(as);
2250  }
2251 };
2252 
2253 // Convert a fixed array-like type TS into a UT_Matrix4T< T >.
2254 // This allows conversion to UT_Matrix4T without fixing T.
2255 // Instead, the element type of TS determines the type T.
2256 template< typename TS >
2258 UTmakeMatrix4T( const TS& as ) noexcept
2259 {
2261 
2262  return UT_Matrix4TFromFixed< T >{}( as );
2263 }
2264 
2265 // UT_FromFixed<V> creates a V from a flat, fixed array-like representation
2266 
2267 // Primary
2268 template <typename V >
2269 struct UT_FromFixed;
2270 
2271 // Partial specialization for UT_Matrix4T
2272 template <typename T>
2274 
2275 template <typename T> template<int ORDER>
2276 void
2277 UT_Matrix4T<T>::rotate(T rx, T ry, T rz)
2278 {
2279  switch(ORDER)
2280  {
2281  case 0://UT_XformOrder::XYZ:
2282  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2283  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2284  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2285  break;
2286 
2287  case 1:
2288  //case UT_XformOrder::XZY:
2289  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2290  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2291  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2292  break;
2293 
2294  case 2:
2295  //case UT_XformOrder::YXZ:
2296  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2297  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2298  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2299  break;
2300 
2301  case 3:
2302  //case UT_XformOrder::YZX:
2303  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2304  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2305  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2306  break;
2307 
2308  case 4:
2309  //case UT_XformOrder::ZXY:
2310  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2311  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2312  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2313  break;
2314 
2315  case 5:
2316  //case UT_XformOrder::ZYX:
2317  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
2318  if(ry) rotate<UT_Axis3::YAXIS>(ry);
2319  if(rx) rotate<UT_Axis3::XAXIS>(rx);
2320  break;
2321 
2322  default:
2323  break;
2324  }
2325 }
2326 
2327 #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
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:2044
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:1447
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
UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix4T< T > &v)
#define VM_STORE
Definition: VM_BasicFunc.h:399
SYS_FORCE_INLINE UT_Matrix4T< T > & operator*=(T scalar)
Definition: UT_Matrix4.h: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:2072
GLboolean invert
Definition: glcorearb.h:549
GLboolean * data
Definition: glcorearb.h:131
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector4.h:493
Define parameters for Houdini's full transform model.
Definition: UT_Matrix4.h: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:1160
SYS_FORCE_INLINE T operator()(unsigned row, unsigned col) const
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix4.h:1175
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:2198
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:1169
SYS_FORCE_INLINE void rotateQuarter()
Definition: UT_Matrix4.h:565
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:1128
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:667
int64 exint
Definition: SYS_Types.h:125
SYS_FORCE_INLINE void prerotate(const UT_Vector3T< T > &rad, const UT_XformOrder &ord)
Definition: UT_Matrix4.h: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:37
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:174
constexpr SYS_FORCE_INLINE UT_Vector3T & operator*=(const T &a) noexcept
Definition: UT_Vector3.h:326
SYS_FORCE_INLINE void shear(const UT_Vector3T< T > &sh)
Definition: UT_Matrix4.h: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:491
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:2106
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:1274
GA_API const UT_StringHolder scale
GLdouble n
Definition: glcorearb.h:2008
static int entries()
Returns the vector size.
Definition: UT_Matrix4.h:1268
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
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4512
constexpr SYS_FORCE_INLINE T & z() noexcept
Definition: UT_Vector4.h:495
bool operator==(const UT_Matrix4T< T > &m) const
Definition: UT_Matrix4.h:277
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
UT_Matrix4T< T > SYSbarycentric(const UT_Matrix4T< T > &v0, const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2, S u, S v)
Barycentric interpolation.
Definition: UT_Matrix4.h:85
void rotate(UT_Vector3T< S > &axis, T theta, int norm=1)
int explode(const UT_XformOrder &order, UT_Vector3F &r, UT_Vector3F &s, UT_Vector3F &t, const UT_Vector3F &p, UT_Vector3F *shears=0) const
Definition: UT_Matrix4.h:969
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:137
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:954
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:1905
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:2258
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:1933
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:2032
void identity()
Set the matrix to identity.
Definition: UT_Matrix4.h:1124
constexpr SYS_FORCE_INLINE UT_Matrix4T< T > operator()(const TS &as) const noexcept
Definition: UT_Matrix4.h:2216
UT_Matrix4T< T > SYSmax(const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2)
Definition: UT_Matrix4.h:2130
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:1944
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:1110
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:4660
SYS_FORCE_INLINE const T * operator()(unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix4.h:1191
GLdouble t
Definition: glad.h:2397
void setTranslates(const UT_Vector3T< S > &translates)
Definition: UT_Matrix4.h:1438
GLfloat v0
Definition: glcorearb.h:816
bool isZero() const
Definition: UT_Matrix4.h:1142
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:1083
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:991
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:1185
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:1159
UT_Matrix4T< T > SYSlerp(const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2, S t)
Definition: UT_Matrix4.h:2154
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:1922
SYS_FORCE_INLINE void scale(T s)
Definition: UT_Matrix4.h:713
T getEuclideanNorm() const
Definition: UT_Matrix4.h:1208
fpreal64 fpreal
Definition: SYS_Types.h:278
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:1126
constexpr SYS_FORCE_INLINE T & w() noexcept
Definition: UT_Vector4.h:497
GLfloat GLfloat v1
Definition: glcorearb.h:817
GLuint GLfloat * val
Definition: glcorearb.h:1608
UT_Matrix4T< T > & operator=(const UT_SymMatrix4T< S > &m)
Conversion from a symmetric to a non symmetric matrix.
Definition: UT_Matrix4.h: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
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:986
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)
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4539
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:1589
GLenum GLenum GLsizei void * row
Definition: glad.h:5135
UT_Matrix4T< T > operator/(const UT_Matrix4T< T > &mat, S sc)
Definition: UT_Matrix4.h:1856
static UT_Matrix4T< T > reflectMat(const UT_Vector3T< S > &plane_origin, const UT_Vector3T< S > &plane_normal)
Definition: UT_Matrix4.h:1098
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:665
SYS_FORCE_INLINE void multiply(UT_Vector3T< T > &dest, const UT_Matrix4T< S > &mat) const
Definition: UT_Matrix4.h:2093
bool SYSisEqual(const UT_Vector2T< T > &a, const UT_Vector2T< T > &b, S tol=SYS_FTOLERANCE)
Componentwise equality.
Definition: UT_Vector2.h:674
unsigned int uint
Definition: SYS_Types.h:45
T matx[4][4]
Definition: UT_Matrix4.h:1273
constexpr SYS_FORCE_INLINE UT_Matrix4T< T > operator()(const TS &as) const noexcept
Definition: UT_Matrix4.h:2245
v4sf vector
Definition: VM_SIMD.h:348
SYS_FORCE_INLINE void multiply3(const UT_Matrix4T< S > &mat)
Definition: UT_Matrix4.h:2065
int explode(const UT_XformOrder &order, UT_Vector3D &r, UT_Vector3D &s, UT_Vector3D &t, UT_Vector3D *shears=0) const
Definition: UT_Matrix4.h:958
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:1464
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:974
void getTranslates(UT_Vector3T< S > &translates) const
Definition: UT_Matrix4.h:1428
void preMultiply(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:348
unsigned hash() const
Compute a hash.
Definition: UT_Matrix4.h:1164
void transpose()
Definition: UT_Matrix4.h:505
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:663