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