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