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