HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros 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 #include <VM/VM_SIMD.h>
26 
27 
28 class UT_IStream;
29 class UT_JSONWriter;
30 class UT_JSONValue;
31 class UT_JSONParser;
32 
33 
34 // Free floating operators that return a UT_Matrix4 object.
35 template <typename T>
36 inline UT_Matrix4T<T> operator+(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2);
37 template <typename T>
38 inline UT_Matrix4T<T> operator-(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2);
39 template <typename T>
40 inline UT_Matrix4T<T> operator*(const UT_Matrix4T<T> &m1, const UT_Matrix4T<T> &m2);
41 template <typename T, typename S>
42 inline UT_Matrix4T<T> operator+(const UT_Matrix4T<T> &mat, const UT_Vector4T<S> &vec);
43 template <typename T, typename S>
44 inline UT_Matrix4T<T> operator+(const UT_Vector4T<S> &vec, const UT_Matrix4T<T> &mat);
45 template <typename T, typename S>
46 inline UT_Matrix4T<T> operator-(const UT_Matrix4T<T> &mat, const UT_Vector4T<S> &vec);
47 template <typename T, typename S>
48 inline UT_Matrix4T<T> operator-(const UT_Vector4T<S> &vec, const UT_Matrix4T<T> &mat);
49 template <typename T, typename S>
50 inline UT_Matrix4T<T> operator+(const UT_Matrix4T<T> &mat, S sc);
51 template <typename T, typename S>
52 inline UT_Matrix4T<T> operator-(const UT_Matrix4T<T> &mat, S sc);
53 template <typename T, typename S>
54 inline UT_Matrix4T<T> operator*(const UT_Matrix4T<T> &mat, S sc);
55 template <typename T, typename S>
56 inline UT_Matrix4T<T> operator/(const UT_Matrix4T<T> &mat, S sc);
57 template <typename T, typename S>
58 inline UT_Matrix4T<T> operator+(S sc, const UT_Matrix4T<T> &mat);
59 template <typename T, typename S>
60 inline UT_Matrix4T<T> operator-(S sc, const UT_Matrix4T<T> &mat);
61 template <typename T, typename S>
62 inline UT_Matrix4T<T> operator*(S sc, const UT_Matrix4T<T> &mat);
63 template <typename T, typename S>
64 inline UT_Matrix4T<T> operator/(S sc, const UT_Matrix4T<T> &mat);
65 
66 template <typename T>
67 inline UT_Matrix4T<T> SYSmin (const UT_Matrix4T<T> &v1, const UT_Matrix4T<T> &v2);
68 template <typename T>
69 inline UT_Matrix4T<T> SYSmax (const UT_Matrix4T<T> &v1, const UT_Matrix4T<T> &v2);
70 template <typename T,typename S>
71 inline UT_Matrix4T<T> SYSlerp(const UT_Matrix4T<T> &v1, const UT_Matrix4T<T> &v2, S t);
72 template <typename T,typename S>
73 inline UT_Matrix4T<T> SYSbilerp(const UT_Matrix4T<T> &u0v0, const UT_Matrix4T<T> &u1v0,
74  const UT_Matrix4T<T> &u0v1, const UT_Matrix4T<T> &u1v1,
75  S u, S v)
76 { return SYSlerp(SYSlerp(u0v0, u0v1, v), SYSlerp(u1v0, u1v1, v), u); }
77 
78 /// This class implements a 4x4 fpreal matrix in row-major order.
79 ///
80 /// Most of Houdini operates with row vectors that are left-multiplied with
81 /// matrices. e.g., z = v * M
82 /// As a result, translation data is in row 3 of the matrix, rather than
83 /// column 3.
84 template <typename T>
86 {
87 public:
88 
89  typedef T value_type;
90  static const int tuple_size = 16;
91 
92  /// Construct uninitialized matrix.
93  SYS_FORCE_INLINE UT_Matrix4T() = default;
94 
95  /// Default copy constructor
96  constexpr UT_Matrix4T(const UT_Matrix4T &) = default;
97 
98  /// Default move constructor
99  constexpr UT_Matrix4T(UT_Matrix4T &&) = default;
100 
101  /// Construct identity matrix, multipled by scalar.
102  explicit constexpr UT_Matrix4T(fpreal64 val) noexcept
103  : matx{
104  {T(val),0,0,0},
105  {0,T(val),0,0},
106  {0,0,T(val),0},
107  {0,0,0,T(val)}}
108  {
109  SYS_STATIC_ASSERT(sizeof(UT_Matrix4T<T>) == tuple_size * sizeof(T));
110  }
111  /// Construct a deep copy of the input row-major data.
112  /// @{
113  template <typename S>
114  explicit constexpr UT_Matrix4T(const S m[4][4]) noexcept
115  : matx{
116  {T(m[0][0]),T(m[0][1]),T(m[0][2]),T(m[0][3])},
117  {T(m[1][0]),T(m[1][1]),T(m[1][2]),T(m[1][3])},
118  {T(m[2][0]),T(m[2][1]),T(m[2][2]),T(m[2][3])},
119  {T(m[3][0]),T(m[3][1]),T(m[3][2]),T(m[3][3])}}
120  {}
121  /// @}
122 
123  /// Arbitrary UT_FixedVector of the same size
124  template <typename S>
126  {
127  matx[0][0]=v[0]; matx[0][1]=v[1]; matx[0][2]=v[2]; matx[0][3]=v[3];
128  matx[1][0]=v[4]; matx[1][1]=v[5]; matx[1][2]=v[6]; matx[1][3]=v[7];
129  matx[2][0]=v[8]; matx[2][1]=v[9]; matx[2][2]=v[10];matx[2][3]=v[11];
130  matx[3][0]=v[12];matx[3][1]=v[13];matx[3][2]=v[14];matx[3][3]=v[15];
131  }
132 
133  /// This constructor is for convenience.
134  UT_Matrix4T(T val00, T val01, T val02, T val03,
135  T val10, T val11, T val12, T val13,
136  T val20, T val21, T val22, T val23,
137  T val30, T val31, T val32, T val33)
138  {
139  matx[0][0] = val00; matx[0][1] = val01; matx[0][2] = val02;
140  matx[0][3] = val03;
141  matx[1][0] = val10; matx[1][1] = val11; matx[1][2] = val12;
142  matx[1][3] = val13;
143  matx[2][0] = val20; matx[2][1] = val21; matx[2][2] = val22;
144  matx[2][3] = val23;
145  matx[3][0] = val30; matx[3][1] = val31; matx[3][2] = val32;
146  matx[3][3] = val33;
147  }
148 
149  /// Base type conversion constructor
150  template <typename S>
151  explicit UT_Matrix4T(const UT_Matrix4T<S> &m)
152  {
153  matx[0][0]=m(0,0); matx[0][1]=m(0,1); matx[0][2]=m(0,2); matx[0][3]=m(0,3);
154  matx[1][0]=m(1,0); matx[1][1]=m(1,1); matx[1][2]=m(1,2); matx[1][3]=m(1,3);
155  matx[2][0]=m(2,0); matx[2][1]=m(2,1); matx[2][2]=m(2,2); matx[2][3]=m(2,3);
156  matx[3][0]=m(3,0); matx[3][1]=m(3,1); matx[3][2]=m(3,2); matx[3][3]=m(3,3);
157  }
158  template <typename S>
159  explicit UT_Matrix4T(const UT_Matrix3T<S> &m)
160  {
161  matx[0][0]=m(0,0); matx[0][1]=m(0,1); matx[0][2]=m(0,2); matx[0][3]=(T)0.;
162  matx[1][0]=m(1,0); matx[1][1]=m(1,1); matx[1][2]=m(1,2); matx[1][3]=(T)0.;
163  matx[2][0]=m(2,0); matx[2][1]=m(2,1); matx[2][2]=m(2,2); matx[2][3]=(T)0.;
164  matx[3][0]=(T)0.; matx[3][1]=(T)0.; matx[3][2]=(T)0.; matx[3][3]=(T)1.;
165  }
166 
167  template<typename S>
169  {
170  *this = m;
171  }
172 
173  /// Default copy assignment operator
174  UT_Matrix4T<T> &operator=(const UT_Matrix4T<T> &m) = default;
175 
176  /// Default move assignment operator
177  UT_Matrix4T<T> &operator=(UT_Matrix4T<T> &&m) = default;
178 
179  /// Conversion operator that expands a 3x3 into a 4x4 matrix by adding a
180  /// row and column of zeroes, except the diagonal element which is 1.
181  // @{
182  template <typename S>
184  {
185  matx[0][0]=m(0,0); matx[0][1]=m(0,1);
186  matx[0][2]=m(0,2); matx[0][3]=(T)0.;
187  matx[1][0]=m(1,0); matx[1][1]=m(1,1);
188  matx[1][2]=m(1,2); matx[1][3]=(T)0.;
189  matx[2][0]=m(2,0); matx[2][1]=m(2,1);
190  matx[2][2]=m(2,2); matx[2][3]=(T)0.;
191  matx[3][0]=(T)0.; matx[3][1]=(T)0.;
192  matx[3][2]=(T)0.; matx[3][3]=(T)1.;
193  return *this;
194  }
195  // @}
196  template <typename S>
198  {
199  matx[0][0]=m(0,0); matx[0][1]=m(0,1);
200  matx[0][2]=m(0,2); matx[0][3]=m(0,3);
201  matx[1][0]=m(1,0); matx[1][1]=m(1,1);
202  matx[1][2]=m(1,2); matx[1][3]=m(1,3);
203  matx[2][0]=m(2,0); matx[2][1]=m(2,1);
204  matx[2][2]=m(2,2); matx[2][3]=m(2,3);
205  matx[3][0]=m(3,0); matx[3][1]=m(3,1);
206  matx[3][2]=m(3,2); matx[3][3]=m(3,3);
207  return *this;
208  }
209 
210  /// Conversion from a symmetric to a non symmetric matrix
211  template <typename S>
213  {
214  matx[0][0] = m.q00; matx[0][1] = m.q01; matx[0][2] = m.q02;
215  matx[0][3] = m.q03; matx[1][0] = m.q01; matx[1][1] = m.q11;
216  matx[1][2] = m.q12; matx[1][3] = m.q13; matx[2][0] = m.q02;
217  matx[2][1] = m.q12; matx[2][2] = m.q22; matx[2][3] = m.q23;
218  matx[3][0] = m.q03; matx[3][1] = m.q13; matx[3][2] = m.q23;
219  matx[3][3] = m.q33;
220  return *this;
221  }
222 
224  {
225  return UT_Matrix4T<T>(
226  -matx[0][0], -matx[0][1], -matx[0][2], -matx[0][3],
227  -matx[1][0], -matx[1][1], -matx[1][2], -matx[1][3],
228  -matx[2][0], -matx[2][1], -matx[2][2], -matx[2][3],
229  -matx[3][0], -matx[3][1], -matx[3][2], -matx[3][3]);
230  }
231 
233  {
234  matx[0][0]+=m.matx[0][0]; matx[0][1]+=m.matx[0][1];
235  matx[0][2]+=m.matx[0][2]; matx[0][3]+=m.matx[0][3];
236 
237  matx[1][0]+=m.matx[1][0]; matx[1][1]+=m.matx[1][1];
238  matx[1][2]+=m.matx[1][2]; matx[1][3]+=m.matx[1][3];
239 
240  matx[2][0]+=m.matx[2][0]; matx[2][1]+=m.matx[2][1];
241  matx[2][2]+=m.matx[2][2]; matx[2][3]+=m.matx[2][3];
242 
243  matx[3][0]+=m.matx[3][0]; matx[3][1]+=m.matx[3][1];
244  matx[3][2]+=m.matx[3][2]; matx[3][3]+=m.matx[3][3];
245  return *this;
246  }
248  {
249  matx[0][0]-=m.matx[0][0]; matx[0][1]-=m.matx[0][1];
250  matx[0][2]-=m.matx[0][2]; matx[0][3]-=m.matx[0][3];
251 
252  matx[1][0]-=m.matx[1][0]; matx[1][1]-=m.matx[1][1];
253  matx[1][2]-=m.matx[1][2]; matx[1][3]-=m.matx[1][3];
254 
255  matx[2][0]-=m.matx[2][0]; matx[2][1]-=m.matx[2][1];
256  matx[2][2]-=m.matx[2][2]; matx[2][3]-=m.matx[2][3];
257 
258  matx[3][0]-=m.matx[3][0]; matx[3][1]-=m.matx[3][1];
259  matx[3][2]-=m.matx[3][2]; matx[3][3]-=m.matx[3][3];
260  return *this;
261  }
262  template<typename S>
263  inline UT_Matrix4T<T> &operator*=(const UT_Matrix4T<S> &m);
264  template<typename S>
265  inline UT_Matrix4T<T> &operator*=(const UT_Matrix3T<S> &m);
266 
267  // test for exact floating point equality.
268  // for equality within a threshold, see isEqual()
269  bool operator==(const UT_Matrix4T<T> &m) const
270  {
271  return (&m == this) || (
272  matx[0][0]==m.matx[0][0] && matx[0][1]==m.matx[0][1] &&
273  matx[0][2]==m.matx[0][2] && matx[0][3]==m.matx[0][3] &&
274 
275  matx[1][0]==m.matx[1][0] && matx[1][1]==m.matx[1][1] &&
276  matx[1][2]==m.matx[1][2] && matx[1][3]==m.matx[1][3] &&
277 
278  matx[2][0]==m.matx[2][0] && matx[2][1]==m.matx[2][1] &&
279  matx[2][2]==m.matx[2][2] && matx[2][3]==m.matx[2][3] &&
280 
281  matx[3][0]==m.matx[3][0] && matx[3][1]==m.matx[3][1] &&
282  matx[3][2]==m.matx[3][2] && matx[3][3]==m.matx[3][3] );
283  }
284 
285  bool operator!=(const UT_Matrix4T<T> &m) const
286  {
287  return !(*this == m);
288  }
289 
290  // Scalar operators:
291  UT_Matrix4T<T> &operator= (fpreal64 v)
292  {
293  matx[0][0]= v; matx[0][1]= 0; matx[0][2]= 0; matx[0][3]= 0;
294  matx[1][0]= 0; matx[1][1]= v; matx[1][2]= 0; matx[1][3]= 0;
295  matx[2][0]= 0; matx[2][1]= 0; matx[2][2]= v; matx[2][3]= 0;
296  matx[3][0]= 0; matx[3][1]= 0; matx[3][2]= 0; matx[3][3]= v;
297  return *this;
298  }
299  /// NOTE: DO NOT use this for scaling the transform,
300  /// since this scales the w column (3) as well,
301  /// causing problems with translation later.
302  /// Use M.scale(scalar) instead.
303  inline UT_Matrix4T<T> &operator*=(T scalar)
304  {
305  matx[0][0]*=scalar; matx[0][1]*=scalar;
306  matx[0][2]*=scalar; matx[0][3]*=scalar;
307 
308  matx[1][0]*=scalar; matx[1][1]*=scalar;
309  matx[1][2]*=scalar; matx[1][3]*=scalar;
310 
311  matx[2][0]*=scalar; matx[2][1]*=scalar;
312  matx[2][2]*=scalar; matx[2][3]*=scalar;
313 
314  matx[3][0]*=scalar; matx[3][1]*=scalar;
315  matx[3][2]*=scalar; matx[3][3]*=scalar;
316  return *this;
317  }
318  inline UT_Matrix4T<T> &operator/=(T scalar)
319  {
320  return operator*=( 1.0f/scalar );
321  }
322 
323  // Vector4 operators:
324  template <typename S>
325  inline UT_Matrix4T<T> &operator=(const UT_Vector4T<S> &vec);
326  template <typename S>
327  inline UT_Matrix4T<T> &operator+=(const UT_Vector4T<S> &vec);
328  template <typename S>
329  inline UT_Matrix4T<T> &operator-=(const UT_Vector4T<S> &vec);
330 
331  // Other matrix operations:
332 
333  /// Multiply the passed-in matrix (on the left) by this (on the right)
334  /// and assign the result to this.
335  /// (operator*= does right-multiplication)
336  /// @{
337  inline void leftMult( const UT_Matrix4T<T> &m );
338  void preMultiply(const UT_Matrix4T<T> &m) { leftMult(m); }
339  /// @}
340 
341  // Return the cofactor of the matrix, ie the determinant of the 3x3
342  // submatrix that results from removing row 'k' and column 'l' from the
343  // 4x4.
344  inline T coFactor(int k, int l) const
345  {
346  int r[3], c[3];
347  T det;
348 
349  // r, c should evaluate to compile time constants
350  coVals(k, r);
351  coVals(l, c);
352 
353  det = matx[r[0]][c[0]]*
354  (matx[r[1]][c[1]]*matx[r[2]][c[2]]-
355  matx[r[1]][c[2]]*matx[r[2]][c[1]]) +
356  matx[r[0]][c[1]]*
357  (matx[r[1]][c[2]]*matx[r[2]][c[0]]-
358  matx[r[1]][c[0]]*matx[r[2]][c[2]]) +
359  matx[r[0]][c[2]]*
360  (matx[r[1]][c[0]]*matx[r[2]][c[1]]-
361  matx[r[1]][c[1]]*matx[r[2]][c[0]]);
362 
363  if ((k ^ l) & 1)
364  det = -det;
365 
366  return det;
367  }
368 
369  T determinant() const
370  {
371  return(matx[0][0]*coFactor(0,0) +
372  matx[0][1]*coFactor(0,1) +
373  matx[0][2]*coFactor(0,2) +
374  matx[0][3]*coFactor(0,3) );
375  }
376  /// Compute determinant of the upper-left 3x3 sub-matrix
377  T determinant3() const
378  {
379  return(matx[0][0]*
380  (matx[1][1]*matx[2][2]-matx[1][2]*matx[2][1]) +
381  matx[0][1]*
382  (matx[1][2]*matx[2][0]-matx[1][0]*matx[2][2]) +
383  matx[0][2]*
384  (matx[1][0]*matx[2][1]-matx[1][1]*matx[2][0]) );
385 
386  }
387  T trace() const
388  { return matx[0][0]+matx[1][1]+matx[2][2]+matx[3][3]; }
389 
390  /// Invert this matrix and return 0 if OK, 1 if singular.
391  // @{
392  int invert(T tol = 0.0F);
393  int invertDouble();
394  // @}
395 
396  /// Invert the matrix and return 0 if OK, 1 if singular.
397  /// Puts the inverted matrix in m, and leaves this matrix unchanged.
398  // @{
399  int invert(UT_Matrix4T<T> &m) const;
400  int invertDouble(UT_Matrix4T<T> &m) const;
401  // @}
402  int invertKramer(void);
403  int invertKramer(UT_Matrix4T<T> &m)const;
404 
405  // Computes a transform to orient to a given direction (v) at a given
406  // position (p) and with a scale (s). The up vector (up) is optional
407  // and will orient the matrix to this up vector. If no up vector is given,
408  // the z axis will be oriented to point in the v direction. If a
409  // quaternion (q) is specified, the orientation will be additionally
410  // transformed by the rotation specified by the quaternion. If a
411  // translation (tr) is specified, the entire frame of reference will
412  // be moved by this translation (unaffected by the scale or rotation).
413  // If an orientation (orient) is specified, the orientation (using the
414  // velocity and up vector) will not be performed and this orientation will
415  // instead be used to define an original orientation.
416  //
417  // The matrix is scaled non-uniformly about each axis using s3, if s3
418  // is non-zero. A uniform scale of pscale is applied regardless, so if
419  // s3 is non-zero, the x axis will be scaled by pscale * s3->x().
420  template <typename S>
421  void instanceT(const UT_Vector3T<S>& p, const UT_Vector3T<S>& v, T s,
422  const UT_Vector3T<S>* s3,
423  const UT_Vector3T<S>* up, const UT_QuaternionT<S>* q,
424  const UT_Vector3T<S>* tr, const UT_QuaternionT<S>* orient,
425  const UT_Vector3T<S>* pivot);
426  void instance(const UT_Vector3F& p, const UT_Vector3F& v, T s,
427  const UT_Vector3F* s3,
428  const UT_Vector3F* up, const UT_QuaternionF* q,
429  const UT_Vector3F* tr, const UT_QuaternionF* orient,
430  const UT_Vector3F* pivot = NULL )
431  { instanceT(p, v, s, s3, up, q, tr, orient, pivot); }
432  void instance(const UT_Vector3D& p, const UT_Vector3D& v, T s,
433  const UT_Vector3D* s3,
434  const UT_Vector3D* up, const UT_QuaternionD* q,
435  const UT_Vector3D* tr, const UT_QuaternionD* orient,
436  const UT_Vector3D* pivot = NULL )
437  { instanceT(p, v, s, s3, up, q, tr, orient, pivot); }
438 
439  template <typename S>
440  void instanceInverseT(const UT_Vector3T<S>& p, const UT_Vector3T<S>& v, T s,
441  const UT_Vector3T<S>* s3,
442  const UT_Vector3T<S>* up, const UT_QuaternionT<S>* q,
443  const UT_Vector3T<S>* tr, const UT_QuaternionT<S>* orient,
444  const UT_Vector3T<S>* pivot);
445  void instanceInverse(const UT_Vector3F& p, const UT_Vector3F& v, T s,
446  const UT_Vector3F* s3,
447  const UT_Vector3F* up, const UT_QuaternionF* q,
448  const UT_Vector3F* tr, const UT_QuaternionF* orient,
449  const UT_Vector3F* pivot = NULL )
450  { instanceInverseT(p, v, s, s3, up, q, tr, orient, pivot); }
451  void instanceInverse(const UT_Vector3D& p, const UT_Vector3D& v, T s,
452  const UT_Vector3D* s3,
453  const UT_Vector3D* up, const UT_QuaternionD* q,
454  const UT_Vector3D* tr, const UT_QuaternionD* orient,
455  const UT_Vector3D* pivot = NULL )
456  { instanceInverseT(p, v, s, s3, up, q, tr, orient, pivot); }
457 
458  // Transpose this matrix or return its transpose.
459  void transpose(void)
460  {
461  T tmp;
462  tmp=matx[0][1]; matx[0][1]=matx[1][0]; matx[1][0]=tmp;
463  tmp=matx[0][2]; matx[0][2]=matx[2][0]; matx[2][0]=tmp;
464  tmp=matx[0][3]; matx[0][3]=matx[3][0]; matx[3][0]=tmp;
465  tmp=matx[1][2]; matx[1][2]=matx[2][1]; matx[2][1]=tmp;
466  tmp=matx[1][3]; matx[1][3]=matx[3][1]; matx[3][1]=tmp;
467  tmp=matx[2][3]; matx[2][3]=matx[3][2]; matx[3][2]=tmp;
468  }
469 
470  // check for equality within a tolerance level
471  bool isEqual( const UT_Matrix4T<T> &m,
472  T tolerance=T(SYS_FTOLERANCE) ) const
473  {
474  return (&m == this) || (
475  SYSisEqual( matx[0][0], m.matx[0][0], tolerance ) &&
476  SYSisEqual( matx[0][1], m.matx[0][1], tolerance ) &&
477  SYSisEqual( matx[0][2], m.matx[0][2], tolerance ) &&
478  SYSisEqual( matx[0][3], m.matx[0][3], tolerance ) &&
479 
480  SYSisEqual( matx[1][0], m.matx[1][0], tolerance ) &&
481  SYSisEqual( matx[1][1], m.matx[1][1], tolerance ) &&
482  SYSisEqual( matx[1][2], m.matx[1][2], tolerance ) &&
483  SYSisEqual( matx[1][3], m.matx[1][3], tolerance ) &&
484 
485  SYSisEqual( matx[2][0], m.matx[2][0], tolerance ) &&
486  SYSisEqual( matx[2][1], m.matx[2][1], tolerance ) &&
487  SYSisEqual( matx[2][2], m.matx[2][2], tolerance ) &&
488  SYSisEqual( matx[2][3], m.matx[2][3], tolerance ) &&
489 
490  SYSisEqual( matx[3][0], m.matx[3][0], tolerance ) &&
491  SYSisEqual( matx[3][1], m.matx[3][1], tolerance ) &&
492  SYSisEqual( matx[3][2], m.matx[3][2], tolerance ) &&
493  SYSisEqual( matx[3][3], m.matx[3][3], tolerance ) );
494  }
495 
496  /// Post-multiply this matrix by a 3x3 rotation matrix determined by the
497  /// axis and angle of rotation in radians.
498  /// If 'norm' is not 0, the axis vector is normalized before computing the
499  /// rotation matrix. rotationMat() returns a rotation matrix, and could as
500  /// well be defined as a free floating function.
501  /// @{
502  template <typename S>
503  void rotate(UT_Vector3T<S> &axis, T theta, int norm=1);
504  void rotate(UT_Axis3::axis a, T theta);
505  /// @}
506 
507  /// Create a rotation matrix for the given angle in radians around the axis
508  /// @{
509  template <typename S>
510  static UT_Matrix4T<T> rotationMat(UT_Vector3T<S> &axis, T theta, int norm=1);
511  static UT_Matrix4T<T> rotationMat(UT_Axis3::axis a, T theta);
512  /// @}
513 
514  /// Pre-multiply this matrix by a 3x3 rotation matrix determined by the
515  /// axis and angle of rotation in radians.
516  /// If 'norm' is not 0, the axis vector is normalized before computing the
517  /// rotation matrix. rotationMat() returns a rotation matrix, and could as
518  /// well be defined as a free floating function.
519  /// @{
520  template <typename S>
521  void prerotate(UT_Vector3T<S> &axis, T theta, int norm=1);
522  void prerotate(UT_Axis3::axis a, T theta);
523  /// @}
524 
525  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
526  /// order given by UT_XformOrder.
527  /// @{
528  void rotate(T rx, T ry, T rz, const UT_XformOrder &ord);
529  inline void rotate(const UT_Vector3T<T> &rad, const UT_XformOrder &ord)
530  { rotate(rad(0), rad(1), rad(2), ord); }
531  /// @}
532 
533  /// Pre-rotate by rx, ry, rz radians around the three basic axes in the
534  /// order given by UT_XformOrder.
535  /// @{
536  void prerotate(T rx, T ry, T rz,
537  const UT_XformOrder &ord);
538  inline void prerotate(const UT_Vector3T<T> &rad, const UT_XformOrder &ord)
539  { prerotate(rad(0), rad(1), rad(2), ord); }
540  /// @}
541 
542  /// Post-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
543  /// @{
544  void scale(T sx, T sy, T sz, T sw = 1.0f)
545  {
546  matx[0][0] *= sx; matx[0][1] *= sy;
547  matx[0][2] *= sz; matx[0][3] *= sw;
548 
549  matx[1][0] *= sx; matx[1][1] *= sy;
550  matx[1][2] *= sz; matx[1][3] *= sw;
551 
552  matx[2][0] *= sx; matx[2][1] *= sy;
553  matx[2][2] *= sz; matx[2][3] *= sw;
554 
555  matx[3][0] *= sx; matx[3][1] *= sy;
556  matx[3][2] *= sz; matx[3][3] *= sw;
557  }
559  { scale(s(0), s(1), s(2)); }
561  { scale(s, s, s); }
562  /// @}
563 
564  /// Pre-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
565  /// @{
566  void prescale(T sx, T sy, T sz, T sw = 1.0f)
567  {
568  matx[0][0] *= sx; matx[1][0] *= sy;
569  matx[2][0] *= sz; matx[3][0] *= sw;
570 
571  matx[0][1] *= sx; matx[1][1] *= sy;
572  matx[2][1] *= sz; matx[3][1] *= sw;
573 
574  matx[0][2] *= sx; matx[1][2] *= sy;
575  matx[2][2] *= sz; matx[3][2] *= sw;
576 
577  matx[0][3] *= sx; matx[1][3] *= sy;
578  matx[2][3] *= sz; matx[3][3] *= sw;
579  }
581  { prescale(s(0), s(1), s(2)); }
583  { prescale(s, s, s); }
584  /// @}
585 
586  /// Post-multiply this matrix by the shear matrix formed by (sxy, sxz, syz)
587  /// @{
588  void shear(T s_xy, T s_xz, T s_yz)
589  {
590  matx[0][0] += matx[0][1]*s_xy + matx[0][2]*s_xz;
591  matx[0][1] += matx[0][2]*s_yz;
592 
593  matx[1][0] += matx[1][1]*s_xy + matx[1][2]*s_xz;
594  matx[1][1] += matx[1][2]*s_yz;
595 
596  matx[2][0] += matx[2][1]*s_xy + matx[2][2]*s_xz;
597  matx[2][1] += matx[2][2]*s_yz;
598 
599  matx[3][0] += matx[3][1]*s_xy + matx[3][2]*s_xz;
600  matx[3][1] += matx[3][2]*s_yz;
601  }
602  inline void shear(const UT_Vector3T<T> &sh)
603  { shear(sh(0), sh(1), sh(2)); }
604  /// @}
605 
606  /// Post-multiply this matrix by the translation determined by dx, dy, dz.
607  /// @{
608  void translate(T dx, T dy, T dz = 0.0f)
609  {
610  T a;
611  a = matx[0][3];
612  matx[0][0] += a*dx; matx[0][1] += a*dy; matx[0][2] += a*dz;
613  a = matx[1][3];
614  matx[1][0] += a*dx; matx[1][1] += a*dy; matx[1][2] += a*dz;
615  a = matx[2][3];
616  matx[2][0] += a*dx; matx[2][1] += a*dy; matx[2][2] += a*dz;
617  a = matx[3][3];
618  matx[3][0] += a*dx; matx[3][1] += a*dy; matx[3][2] += a*dz;
619  }
620  inline void translate(const UT_Vector3T<T> &delta)
621  { translate(delta(0), delta(1), delta(2)); }
622  /// @}
623 
624  /// Pre-multiply this matrix by the translation determined by dx, dy, dz.
625  /// @{
626  void pretranslate(T dx, T dy, T dz = 0.0f)
627  {
628  matx[3][0] += matx[0][0]*dx + matx[1][0]*dy + matx[2][0]*dz;
629  matx[3][1] += matx[0][1]*dx + matx[1][1]*dy + matx[2][1]*dz;
630  matx[3][2] += matx[0][2]*dx + matx[1][2]*dy + matx[2][2]*dz;
631  matx[3][3] += matx[0][3]*dx + matx[1][3]*dy + matx[2][3]*dz;
632  }
633  inline void pretranslate(const UT_Vector3T<T> &delta)
634  { pretranslate(delta(0), delta(1), delta(2)); }
635  /// @}
636 
637  // Space change operation: right multiply this matrix by the 3x3 matrix
638  // of the transformation which moves the vector space defined by
639  // (iSrc, jSrc, cross(iSrc,jSrc)) into the space defined by
640  // (iDest, jDest, cross(iDest,jDest)). iSrc, jSrc, iDest, and jDest will
641  // be normalized before the operation if norm is 1. This matrix transforms
642  // iSrc into iDest, and jSrc into jDest.
643  template <typename S>
644  void changeSpace(UT_Vector3T<S> &iSrc, UT_Vector3T<S> &jSrc,
645  UT_Vector3T<S> &iDest,UT_Vector3T<S> &jDest,
646  int norm=1);
647 
648  // Multiply this matrix by the general transform matrix built from
649  // translations (tx,ty,tz), degree rotations (rx,ry,rz), scales (sx,sy,sz),
650  // and possibly a pivot point (px,py,pz). The second methos leaves us
651  // unchanged, and returns a new (this*xform) instead. The order of the
652  // multiplies (SRT, RST, RxRyRz, etc) is stored in 'order'. Normally you
653  // will ignore the 'reverse' parameter, which tells us to build the
654  // matrix from last to first xform, and to apply some inverses to
655  // txyz, rxyz, and sxyz.
656  void xform(const UT_XformOrder &order,
657  T tx=0.0f, T ty=0.0f, T tz=0.0f,
658  T rx=0.0f, T ry=0.0f, T rz=0.0f,
659  T sx=1.0f, T sy=1.0f, T sz=1.0f,
660  T px=0.0f, T py=0.0f, T pz=0.0f,
661  int reverse=0);
662 
663  // This version handles shears as well
664  void xform(const UT_XformOrder &order,
665  T tx, T ty, T tz,
666  T rx, T ry, T rz,
667  T sx, T sy, T sz,
668  T s_xy, T s_xz, T s_yz,
669  T px, T py, T pz,
670  int reverse=0);
671 
672  /// Define parameters for Houdini's pivot space.
673  template <typename S>
674  struct PivotSpaceT
675  {
676  /// Constructor with default values for data members
678  : myTranslate(0, 0, 0)
679  , myRotate(0, 0, 0)
680  {
681  }
682 
683  /// Convenience constructor with translate and rotate.
684  PivotSpaceT(const UT_Vector3T<S> &translate,
685  const UT_Vector3T<S> &rotate)
686  : myTranslate(translate)
687  , myRotate(rotate)
688  {
689  }
690 
691  UT_Vector3T<S> myTranslate; // Translate (corresponds to px, py, pz)
692  UT_Vector3T<S> myRotate; // Rotation (degrees, XYZ order)
693  };
694 
695  typedef PivotSpaceT<T> PivotSpace;
696 
697  // This version handles a more general PivotSpace.
698  void xform(const UT_XformOrder &order,
699  T tx, T ty, T tz,
700  T rx, T ry, T rz,
701  T sx, T sy, T sz,
702  const PivotSpace &pivot,
703  int reverse=0);
704 
705  // This version handles a more general PivotSpace as well as shears.
706  void xform(const UT_XformOrder &order,
707  T tx, T ty, T tz,
708  T rx, T ry, T rz,
709  T sx, T sy, T sz,
710  T s_xy, T s_xz, T s_yz,
711  const PivotSpace &pivot,
712  int reverse=0);
713 
714  /// Define parameters for Houdini's full transform model
716  {
717  /// Constructor with default values for data members
719  : myOrder(UT_XformOrder::SRT, UT_XformOrder::XYZ)
720  , myTranslate(0, 0, 0)
721  , myRotateOffset(0, 0, 0)
722  , myParentRotate(0, 0, 0)
723  , myRotate(0, 0, 0)
724  , myChildRotate(0, 0, 0)
725  , myRotatePivot(0, 0, 0)
726  , myScaleOffset(0, 0, 0)
727  , myScale(1, 1, 1)
728  , myShear(0, 0, 0)
729  , myScalePivot(0, 0, 0)
730  , myPivot(0, 0, 0)
731  , myPivotRotate(0, 0, 0)
732  {
733  }
734 
735  UT_XformOrder myOrder; /// transform and rotation order
737  UT_Vector3T<T> myRotateOffset; /// Rotation offset
738  UT_Vector3T<T> myParentRotate; /// Parent rotation (degrees, XYZ order)
739  UT_Vector3T<T> myRotate; /// Rotation (degrees, myOrder order)
740  UT_Vector3T<T> myChildRotate; /// Child rotation (degrees, XYZ order)
741  UT_Vector3T<T> myRotatePivot; /// Rotation pivot
742  UT_Vector3T<T> myScaleOffset; /// Scale offset
744  UT_Vector3T<T> myShear; /// Shear (within scale pivot)
745  UT_Vector3T<T> myScalePivot; /// Scale pivot
746  UT_Vector3T<T> myPivot; /// Overall pivot
747  UT_Vector3T<T> myPivotRotate; /// Overall pivot rotation(degrees,XYZ)
748  };
749 
750  void xform(const FullTransformModel &parms, T min_abs_scale = T(0));
751 
752  // These versions of xform and rotate can be used to apply selected parts
753  // of a transform. The applyType controls how far into the xform
754  // it should go. For example: applyXform(order, BEFORE_EQUAL, 'T', ...)
755  // will apply all the components of the transform up to and equal to the
756  // translates (depending on UT_XformOrder)
757  //
758  // For xform char can be T, R, S, P, or p (P is for pivot)
759  // For rotate char can be X, Y, or Z
760  //
761  // TODO add a reverse option
762 
763  enum applyType { BEFORE=1, EQUAL=2, AFTER=4, BEFORE_EQUAL=4, AFTER_EQUAL=6};
764  void xform(const UT_XformOrder &order,
765  applyType type, char limit,
766  T tx, T ty, T tz,
767  T rx, T ry, T rz,
768  T sx, T sy, T sz,
769  T px, T py, T pz);
770 
771  void rotate(const UT_XformOrder &order,
772  applyType type, char limit,
773  T rx, T ry, T rz);
774 
775  // extract only the translates from the matrix;
776  template <typename S>
777  inline void getTranslates(UT_Vector3T<S> &translates) const;
778  template <typename S>
779  inline void setTranslates(const UT_Vector3T<S> &translates);
780 
781  // This is a super-crack that returns the translation, scale, and radian
782  // rotation vectors given a transformation order and a valid xform matrix.
783  // It returns 0 if succesful, and non-zero otherwise: 1 if the embedded
784  // rotation matrix is invalid, 2 if the rotation order is invalid,
785  // and 3 for other problems. If any of the scaling values is 0, the method
786  // returns all zeroes, and a 0 return value.
787  template <typename S>
788  int explodeT(const UT_XformOrder &order,
790  UT_Vector3T<S> *shears) const;
791  int explode(const UT_XformOrder &order,
793  UT_Vector3F *shears = 0) const
794  { return explodeT(order, r, s, t, shears); }
795  int explode(const UT_XformOrder &order,
797  UT_Vector3D *shears = 0) const
798  { return explodeT(order, r, s, t, shears); }
799 
800  // This version of explode returns the t, r, and s, given a pivot value.
801  template <typename S>
802  int explodeT(const UT_XformOrder &order,
804  UT_Vector3T<S> &t, const UT_Vector3T<S> &p,
805  UT_Vector3T<S> *shears) const;
806  int explode(const UT_XformOrder &order,
808  UT_Vector3F &t, const UT_Vector3F &p,
809  UT_Vector3F *shears = 0) const
810  { return explodeT(order, r, s, t, p, shears); }
811  int explode(const UT_XformOrder &order,
813  UT_Vector3D &t, const UT_Vector3D &p,
814  UT_Vector3D *shears = 0) const
815  { return explodeT(order, r, s, t, p, shears); }
816 
817  // This version of explode returns the t, r, and s, given a PivotSpace.
818  template <typename S>
819  int explodeT(const UT_XformOrder &order,
821  UT_Vector3T<S> &t, const PivotSpaceT<S> &p,
822  UT_Vector3T<S> *shears) const;
823  int explode(const UT_XformOrder &order,
825  UT_Vector3F &t, const PivotSpaceT<fpreal32> &p,
826  UT_Vector3F *shears = 0) const
827  { return explodeT(order, r, s, t, p, shears); }
828  int explode(const UT_XformOrder &order,
830  UT_Vector3D &t, const PivotSpaceT<fpreal64> &p,
831  UT_Vector3D *shears = 0) const
832  { return explodeT(order, r, s, t, p, shears); }
833 
834 
835  // These versions treat the matrix as only containing a 2D
836  // transformation, that is in x, y, with a rotate around z.
837  template <typename S>
838  int explode2D(const UT_XformOrder &order,
839  T &r, UT_Vector2T<S> &s, UT_Vector2T<S> &t,
840  T *shears = 0) const;
841 
842  template <typename S>
843  int explode2D(const UT_XformOrder &order,
844  T &r, UT_Vector2T<S> &s,
845  UT_Vector2T<S> &t, const UT_Vector2T<S> &p,
846  T *shears = 0) const;
847 
848  /// WARNING: This may not produce good results! Instead, get the
849  /// UT_Matrix3 part and call UT_Matrix3T::makeRotationMatrix().
850  template <typename S>
851  void extractRotate(UT_Matrix3T<S> &dst) const;
852 
853  /// Perform the polar decomposition of the 3x3 matrix M into an orthogonal
854  /// matrix Q and an symmetric positive-semidefinite matrix S. This is more
855  /// useful than explode() or extractRotate() when the desire is to blend
856  /// transforms. By default, it gives M=SQ, a left polar decomposition. If
857  /// reverse is false, then it gives M=QS, a right polar decomposition.
858  ///
859  /// This method is similar to the UT_Matrix3 version except it only
860  /// operates on the upper-right 3x3 portion.
861  ///
862  /// @pre The upper-right 3x3 portion of *this is non-singular
863  /// @post The upper-right 3x3 porition = Q,
864  /// and if stretch != 0: *stretch = S.
865  /// @return True if successful
866  bool polarDecompose(
867  UT_Matrix3T<T> *stretch = nullptr,
868  bool reverse = true,
869  const int max_iter = 64,
870  const T rel_tol = FLT_EPSILON);
871 
872  /// Turn this matrix into the "closest" rigid transformation
873  /// (only rotations and translations) matrix.
874  ///
875  /// It uses polarDecompose and then negates the matrix if
876  /// there is a negative determinant (scale). It returns false iff
877  /// polarDecompose failed, possibly due to a singular matrix.
878  ///
879  /// This is currently the one true way to turn an arbitrary
880  /// matrix4 into a rotation and translation matrix. If that
881  /// ever changes, put a warning here, and you may want to update
882  /// UT_Matrix3::makeRotationMatrix too.
883  bool makeRigidMatrix(
884  UT_Matrix3T<T> *stretch = nullptr,
885  bool reverse = true,
886  const int max_iter = 64,
887  const T rel_tol = FLT_EPSILON);
888 
889  // Right multiply this matrix by a 3x3 matrix which scales by a given
890  // amount along the direction of vector v. When applied to a vector w,
891  // the stretched matrix (*this) stretches w in v by the amount given.
892  // If norm is non-zero, v will be normalized prior to the operation.
893  template <typename S>
894  void stretch(UT_Vector3T<S> &v, T amount, int norm=1);
895 
896  T dot(unsigned i, unsigned j) const
897  {
898  return (i <= 3 && j <= 3) ?
899  matx[i][0]*matx[j][0] + matx[i][1]*matx[j][1] +
900  matx[i][2]*matx[j][2] + matx[i][3]*matx[j][3] : (T)0;
901  }
902 
903  // Matrix += b * v1 * v2T
904  template <typename S>
905  void outerproductUpdate(T b,
906  const UT_Vector4T<S> &v1, const UT_Vector4T<S> &v2);
907 
908  // Sets the current matrix to a linear interpolation of the two homogenous
909  // matrices given.
910  void lerp(const UT_Matrix4T<T> &a, const UT_Matrix4T<T> &b, T t)
911  {
912  if (t == 0)
913  *this = a;
914  else if(t == 1)
915  *this = b;
916  else
917  {
918  for (size_t i = 0; i < tuple_size; i++)
919  myFloats[i] = SYSlerp(a.myFloats[i], b.myFloats[i], t);
920  }
921  }
922 
923  /// Set the matrix to identity
924  void identity() { *this = 1; }
925  /// Set the matrix to zero
926  void zero() { *this = 0; }
927 
928  int isIdentity() const
929  {
930  // NB: DO NOT USE TOLERANCES!
931  return(
932  matx[0][0]==1.0f && matx[0][1]==0.0f &&
933  matx[0][2]==0.0f && matx[0][3]==0.0f &&
934  matx[1][0]==0.0f && matx[1][1]==1.0f &&
935  matx[1][2]==0.0f && matx[1][3]==0.0f &&
936  matx[2][0]==0.0f && matx[2][1]==0.0f &&
937  matx[2][2]==1.0f && matx[2][3]==0.0f &&
938  matx[3][0]==0.0f && matx[3][1]==0.0f &&
939  matx[3][2]==0.0f && matx[3][3]==1.0f);
940  }
941 
942  int isZero() const
943  {
944  // NB: DO NOT USE TOLERANCES!
945  return(
946  matx[0][0]==0.0f && matx[0][1]==0.0f &&
947  matx[0][2]==0.0f && matx[0][3]==0.0f &&
948  matx[1][0]==0.0f && matx[1][1]==0.0f &&
949  matx[1][2]==0.0f && matx[1][3]==0.0f &&
950  matx[2][0]==0.0f && matx[2][1]==0.0f &&
951  matx[2][2]==0.0f && matx[2][3]==0.0f &&
952  matx[3][0]==0.0f && matx[3][1]==0.0f &&
953  matx[3][2]==0.0f && matx[3][3]==0.0f);
954  }
955 
956 
957  /// Return the raw matrix data.
958  // @{
959  const T *data(void) const { return myFloats; }
960  T *data(void) { return myFloats; }
961  // @}
962 
963  /// Compute a hash
964  unsigned hash() const { return SYSvector_hash(data(), tuple_size); }
965 
966  /// Return a matrix entry. No bounds checking on subscripts.
967  // @{
969  T &operator()(unsigned row, unsigned col)
970  {
971  UT_ASSERT_P(row < 4 && col < 4);
972  return matx[row][col];
973  }
975  T operator()(unsigned row, unsigned col) const
976  {
977  UT_ASSERT_P(row < 4 && col < 4);
978  return matx[row][col];
979  }
980  // @}
981 
982  /// Return a matrix row. No bounds checking on subscript.
983  // @{
985  T *operator()(unsigned row)
986  {
987  UT_ASSERT_P(row < 4);
988  return matx[row];
989  }
991  const T *operator()(unsigned row) const
992  {
993  UT_ASSERT_P(row < 4);
994  return matx[row];
995  }
996  inline
997  const UT_Vector4T<T> &operator[](unsigned row) const;
998  inline
999  UT_Vector4T<T> &operator[](unsigned row);
1000  // @}
1001 
1002  /// Euclidean or Frobenius norm of a matrix.
1003  /// Does sqrt(sum(a_ij ^2))
1005  { return SYSsqrt(getEuclideanNorm2()); }
1006  /// Euclidean norm squared.
1007  T getEuclideanNorm2() const;
1008 
1009 
1010  // I/O methods. Return 0 if read/write successful, -1 if unsuccessful.
1011  int save(std::ostream &os, int binary) const;
1012  bool load(UT_IStream &is);
1013  void dump(const char *msg="") const;
1014 
1015  void outAsciiNoName(std::ostream &os) const;
1016 
1017  /// @{
1018  /// Methods to serialize to a JSON stream. The matrix is stored as an
1019  /// array of 16 reals.
1020  bool save(UT_JSONWriter &w) const;
1021  bool save(UT_JSONValue &v) const;
1022  bool load(UT_JSONParser &p);
1023  /// @}
1024 
1025  static const UT_Matrix4T<T> &getIdentityMatrix();
1026 
1027  // I/O friends:
1028  friend std::ostream &operator<<(std::ostream &os, const UT_Matrix4T<T> &v)
1029  {
1030  v.writeClassName(os);
1031  v.outAsciiNoName(os);
1032  return os;
1033  }
1034 
1035  /// Returns the vector size
1036  static int entries() { return tuple_size; }
1037 
1038 
1039  // The matrix data:
1040  union {
1041  T matx[4][4];
1042  T myFloats[tuple_size];
1043  };
1044 
1045  /// Create a perspective projection matrix with the given parameters.
1046  /// This can be used to project points onto the so-called NDC coordinates
1047  /// of a camera. For example, given a point @c P (in the space of a
1048  /// camera):
1049  /// @code
1050  /// UT_Vector3 ndc;
1051  /// UT_Matrix4R proj;
1052  /// proj.perspective(zoom, image_aspect);
1053  /// ndc = P * proj;
1054  /// @endcode
1055  ///
1056  /// - @c zoom @n The zoom for the lens
1057  /// - @c image_aspect @n The aspect ratio of the image
1058  /// - @c pixel_aspect @n The pixel aspect (the aspect ratio of pixels)
1059  /// - @c near,far @n The near/far clipping planes
1060  /// - @c window @n The offset for the projection window.
1061  ///
1062  /// The projection transform will transform the z coordinate of the camera
1063  /// space point such that the near coordinate will map to 0 and the far
1064  /// coordinate will map to 1.
1065  /// That is <tt>n dz.z = fit(P.z, near, far, 0, 1); </tt>.
1066  /// Thus, if the near/far are set to 0/1, the NDC z-coordinate will
1067  /// be the same as the camera space z. If the near/far are set to 0/-1,
1068  /// the Z coordinate will be negated.
1069  ///
1070  /// @note Sometimes the @c zoom is expressed in terms of @c focal and @c
1071  /// aperture. In this case: <tt> zoom = focal/aperture </tt>
1072  /// @note Sometimes the @c image_aspect is expressed in terms of @c xres
1073  /// and @c yres. In this case: <tt> image_aspect = xres / yres </tt>
1074  /// @note To make a single transform from world space to NDC space given a
1075  /// camera matrix and a projection matrix, you would use
1076  /// <tt> worldToNDC = worldToCamera * projection; </tt>
1077  ///
1078  void perspective(fpreal zoom,
1079  fpreal image_aspect,
1080  fpreal pixel_aspect=1,
1081  fpreal clip_near=0, fpreal clip_far=1,
1082  fpreal window_xmin=0, fpreal window_xmax=1,
1083  fpreal window_ymin=0, fpreal window_ymax=1);
1084  /// Create an orthographic projection matrix with the given parameters.
1085  /// This can be used to project points onto the so-called NDC coordinates
1086  /// of a camera. For example, given a point @c P (in the space of a
1087  /// camera):
1088  /// @code
1089  /// UT_Vector3 ndc;
1090  /// UT_Matrix4R proj;
1091  /// proj.orthographic(zoom, 1, image_aspect);
1092  /// ndc = P * proj;
1093  /// @endcode
1094  ///
1095  /// - @c zoom @n The zoom for the lens
1096  /// - @c orthowidth @n An additional "zoom" factor
1097  /// - @c image_aspect @n The resolution of the image
1098  /// - @c pixel_aspect @n The pixel aspect (the aspect ratio of pixels)
1099  /// - @c near,far @n The near/far clipping planes
1100  /// - @c window @n The offset for the projection window.
1101  ///
1102  /// The projection transform will transform the z coordinate of the camera
1103  /// space point such that the near coordinate will map to 0 and the far
1104  /// coordinate will map to 1.
1105  /// That is <tt>n dz.z = fit(P.z, near, far, 0, 1); </tt>.
1106  /// Thus, if the near/far are set to 0/1, the NDC z-coordinate will
1107  /// be the same as the camera space z. If the near/far are set to 0/-1,
1108  /// the Z coordinate will be negated.
1109  ///
1110  /// @note Sometimes the @c zoom is expressed in terms of @c focal and @c
1111  /// aperture. In this case: <tt> zoom = focal/aperture </tt>
1112  /// @note Sometimes the @c image_aspect is expressed in terms of @c xrex
1113  /// and @c yres. In this case: <tt> image_aspect = xres / yres </tt>
1114  /// @note To make a single transform from world space to NDC space given a
1115  /// camera matrix and a projection matrix, you would use
1116  /// <tt> worldToNDC = worldToCamera * projection; </tt>
1117  ///
1118  void orthographic(fpreal zoom,
1119  fpreal orthowidth,
1120  fpreal image_aspect,
1121  fpreal pixel_aspect=1,
1122  fpreal clip_near=0, fpreal clip_far=1,
1123  fpreal window_xmin=0, fpreal window_xmax=1,
1124  fpreal window_ymin=0, fpreal window_ymax=1);
1125 
1126 private:
1127  // Operation to aid in cofactor computation
1128  inline void coVals(int k, int r[3]) const
1129  {
1130  switch (k)
1131  {
1132  case 0: r[0] = 1; r[1] = 2; r[2] = 3; break;
1133  case 1: r[0] = 0; r[1] = 2; r[2] = 3; break;
1134  case 2: r[0] = 0; r[1] = 1; r[2] = 3; break;
1135  case 3: r[0] = 0; r[1] = 1; r[2] = 2; break;
1136  }
1137  }
1138 
1139  static UT_Matrix4T<T> theIdentityMatrix;
1140 
1141  void writeClassName(std::ostream &os) const;
1142  static const char *className();
1143 };
1144 
1145 // Vector4 operators:
1146 
1147 template <typename T>
1148 template <typename S>
1149 inline
1151 {
1152  matx[0][0] = matx[0][1] = matx[0][2] = matx[0][3] = vec.x();
1153  matx[1][0] = matx[1][1] = matx[1][2] = matx[1][3] = vec.y();
1154  matx[2][0] = matx[2][1] = matx[2][2] = matx[2][3] = vec.z();
1155  matx[3][0] = matx[3][1] = matx[3][2] = matx[3][3] = vec.w();
1156  return *this;
1157 }
1158 
1159 template <typename T>
1160 template <typename S>
1161 inline
1163 {
1164  T x = vec.x(); T y = vec.y();
1165  T z = vec.z(); T w = vec.w();
1166  matx[0][0]+=x; matx[0][1]+=x; matx[0][2]+=x; matx[0][3]+=x;
1167  matx[1][0]+=y; matx[1][1]+=y; matx[1][2]+=y; matx[1][3]+=y;
1168  matx[2][0]+=z; matx[2][1]+=z; matx[2][2]+=z; matx[2][3]+=z;
1169  matx[3][0]+=w; matx[3][1]+=w; matx[3][2]+=w; matx[3][3]+=w;
1170  return *this;
1171 }
1172 
1173 template <typename T>
1174 template <typename S>
1175 inline
1177 {
1178  T x = vec.x(); T y = vec.y();
1179  T z = vec.z(); T w = vec.w();
1180  matx[0][0]-=x; matx[0][1]-=x; matx[0][2]-=x; matx[0][3]-=x;
1181  matx[1][0]-=y; matx[1][1]-=y; matx[1][2]-=y; matx[1][3]-=y;
1182  matx[2][0]-=z; matx[2][1]-=z; matx[2][2]-=z; matx[2][3]-=z;
1183  matx[3][0]-=w; matx[3][1]-=w; matx[3][2]-=w; matx[3][3]-=w;
1184  return *this;
1185 }
1186 
1187 template <typename T>
1188 template <typename S>
1189 inline
1191 {
1192  translates.x() = matx[3][0];
1193  translates.y() = matx[3][1];
1194  translates.z() = matx[3][2];
1195 }
1196 
1197 template <typename T>
1198 template <typename S>
1199 inline
1201 {
1202  matx[3][0] = translates.x();
1203  matx[3][1] = translates.y();
1204  matx[3][2] = translates.z();
1205 }
1206 
1207 template <typename T>
1208 inline
1210 {
1211  UT_ASSERT_P(row < 4);
1212  return *(const UT_Vector4T<T>*)(matx[row]);
1213 }
1214 
1215 template <typename T>
1216 inline
1218 {
1219  UT_ASSERT_P(row < 4);
1220  return *(UT_Vector4T<T>*)(matx[row]);
1221 }
1222 
1223 template <typename T>
1224 template <typename S>
1225 inline UT_Matrix4T<T> &
1227 {
1228  T a, b, c, d;
1229  a = matx[0][0]; b = matx[0][1]; c = matx[0][2]; d = matx[0][3];
1230  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1231  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1232  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1233  matx[0][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1234 
1235  a = matx[1][0]; b = matx[1][1]; c = matx[1][2]; d = matx[1][3];
1236  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1237  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1238  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1239  matx[1][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1240 
1241  a = matx[2][0]; b = matx[2][1]; c = matx[2][2]; d = matx[2][3];
1242  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1243  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1244  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1245  matx[2][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1246 
1247  a = matx[3][0]; b = matx[3][1]; c = matx[3][2]; d = matx[3][3];
1248  matx[3][0] = a*m(0,0) + b*m(1,0) + c*m(2,0) + d*m(3,0);
1249  matx[3][1] = a*m(0,1) + b*m(1,1) + c*m(2,1) + d*m(3,1);
1250  matx[3][2] = a*m(0,2) + b*m(1,2) + c*m(2,2) + d*m(3,2);
1251  matx[3][3] = a*m(0,3) + b*m(1,3) + c*m(2,3) + d*m(3,3);
1252  return *this;
1253 }
1254 
1255 #if 1
1256 template <>
1257 template <>
1258 inline UT_Matrix4T<float> &
1260 {
1261  v4uf m0(m.matx[0]);
1262  v4uf m1(m.matx[1]);
1263  v4uf m2(m.matx[2]);
1264  v4uf m3(m.matx[3]);
1265 
1266  v4uf row;
1267 
1268  for (int i = 0; i < 4; i++)
1269  {
1270  row = m0 * v4uf(matx[i][0]);
1271  row += m1 * v4uf(matx[i][1]);
1272  row += m2 * v4uf(matx[i][2]);
1273  row += m3 * v4uf(matx[i][3]);
1274 
1275  VM_STORE(matx[i], row.vector);
1276  }
1277  return *this;
1278 }
1279 #endif
1280 
1281 template <typename T>
1282 template <typename S>
1283 inline UT_Matrix4T<T> &
1285 {
1286  T a, b, c;
1287  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
1288  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1289  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1290  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1291 
1292  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
1293  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1294  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1295  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1296 
1297  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
1298  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1299  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1300  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1301 
1302  a = matx[3][0]; b = matx[3][1]; c = matx[3][2];
1303  matx[3][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
1304  matx[3][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
1305  matx[3][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
1306  return *this;
1307 }
1308 
1309 template <typename T>
1310 inline void
1312 {
1313  T a, b, c, d;
1314  a = matx[0][0]; b = matx[1][0]; c = matx[2][0]; d = matx[3][0];
1315  matx[0][0] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1316  matx[1][0] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1317  matx[2][0] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1318  matx[3][0] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1319 
1320  a = matx[0][1]; b = matx[1][1]; c = matx[2][1]; d = matx[3][1];
1321  matx[0][1] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1322  matx[1][1] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1323  matx[2][1] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1324  matx[3][1] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1325 
1326  a = matx[0][2]; b = matx[1][2]; c = matx[2][2]; d = matx[3][2];
1327  matx[0][2] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1328  matx[1][2] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1329  matx[2][2] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1330  matx[3][2] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1331 
1332  a = matx[0][3]; b = matx[1][3]; c = matx[2][3]; d = matx[3][3];
1333  matx[0][3] = a*m(0,0) + b*m(0,1) + c*m(0,2) + d*m(0,3);
1334  matx[1][3] = a*m(1,0) + b*m(1,1) + c*m(1,2) + d*m(1,3);
1335  matx[2][3] = a*m(2,0) + b*m(2,1) + c*m(2,2) + d*m(2,3);
1336  matx[3][3] = a*m(3,0) + b*m(3,1) + c*m(3,2) + d*m(3,3);
1337 }
1338 
1339 // Free floating functions:
1340 template <typename T>
1341 inline UT_Matrix4T<T>
1343 {
1344  T m[4][4];
1345  m[0][0] = m1(0,0)+m2(0,0); m[0][1] = m1(0,1)+m2(0,1);
1346  m[0][2] = m1(0,2)+m2(0,2); m[0][3] = m1(0,3)+m2(0,3);
1347 
1348  m[1][0] = m1(1,0)+m2(1,0); m[1][1] = m1(1,1)+m2(1,1);
1349  m[1][2] = m1(1,2)+m2(1,2); m[1][3] = m1(1,3)+m2(1,3);
1350 
1351  m[2][0] = m1(2,0)+m2(2,0); m[2][1] = m1(2,1)+m2(2,1);
1352  m[2][2] = m1(2,2)+m2(2,2); m[2][3] = m1(2,3)+m2(2,3);
1353 
1354  m[3][0] = m1(3,0)+m2(3,0); m[3][1] = m1(3,1)+m2(3,1);
1355  m[3][2] = m1(3,2)+m2(3,2); m[3][3] = m1(3,3)+m2(3,3);
1356  return UT_Matrix4T<T>(m);
1357 }
1358 template <typename T>
1359 inline UT_Matrix4T<T>
1361 {
1362  T m[4][4];
1363  m[0][0] = m1(0,0)-m2(0,0); m[0][1] = m1(0,1)-m2(0,1);
1364  m[0][2] = m1(0,2)-m2(0,2); m[0][3] = m1(0,3)-m2(0,3);
1365 
1366  m[1][0] = m1(1,0)-m2(1,0); m[1][1] = m1(1,1)-m2(1,1);
1367  m[1][2] = m1(1,2)-m2(1,2); m[1][3] = m1(1,3)-m2(1,3);
1368 
1369  m[2][0] = m1(2,0)-m2(2,0); m[2][1] = m1(2,1)-m2(2,1);
1370  m[2][2] = m1(2,2)-m2(2,2); m[2][3] = m1(2,3)-m2(2,3);
1371 
1372  m[3][0] = m1(3,0)-m2(3,0); m[3][1] = m1(3,1)-m2(3,1);
1373  m[3][2] = m1(3,2)-m2(3,2); m[3][3] = m1(3,3)-m2(3,3);
1374  return UT_Matrix4T<T>(m);
1375 }
1376 template <typename T>
1377 inline UT_Matrix4T<T>
1379 {
1380  T m[4][4];
1381  m[0][0] = m1(0,0)*m2(0,0) + m1(0,1)*m2(1,0) +
1382  m1(0,2)*m2(2,0) + m1(0,3)*m2(3,0) ;
1383  m[0][1] = m1(0,0)*m2(0,1) + m1(0,1)*m2(1,1) +
1384  m1(0,2)*m2(2,1) + m1(0,3)*m2(3,1) ;
1385  m[0][2] = m1(0,0)*m2(0,2) + m1(0,1)*m2(1,2) +
1386  m1(0,2)*m2(2,2) + m1(0,3)*m2(3,2) ;
1387  m[0][3] = m1(0,0)*m2(0,3) + m1(0,1)*m2(1,3) +
1388  m1(0,2)*m2(2,3) + m1(0,3)*m2(3,3) ;
1389 
1390  m[1][0] = m1(1,0)*m2(0,0) + m1(1,1)*m2(1,0) +
1391  m1(1,2)*m2(2,0) + m1(1,3)*m2(3,0) ;
1392  m[1][1] = m1(1,0)*m2(0,1) + m1(1,1)*m2(1,1) +
1393  m1(1,2)*m2(2,1) + m1(1,3)*m2(3,1) ;
1394  m[1][2] = m1(1,0)*m2(0,2) + m1(1,1)*m2(1,2) +
1395  m1(1,2)*m2(2,2) + m1(1,3)*m2(3,2) ;
1396  m[1][3] = m1(1,0)*m2(0,3) + m1(1,1)*m2(1,3) +
1397  m1(1,2)*m2(2,3) + m1(1,3)*m2(3,3) ;
1398 
1399  m[2][0] = m1(2,0)*m2(0,0) + m1(2,1)*m2(1,0) +
1400  m1(2,2)*m2(2,0) + m1(2,3)*m2(3,0) ;
1401  m[2][1] = m1(2,0)*m2(0,1) + m1(2,1)*m2(1,1) +
1402  m1(2,2)*m2(2,1) + m1(2,3)*m2(3,1) ;
1403  m[2][2] = m1(2,0)*m2(0,2) + m1(2,1)*m2(1,2) +
1404  m1(2,2)*m2(2,2) + m1(2,3)*m2(3,2) ;
1405  m[2][3] = m1(2,0)*m2(0,3) + m1(2,1)*m2(1,3) +
1406  m1(2,2)*m2(2,3) + m1(2,3)*m2(3,3) ;
1407 
1408  m[3][0] = m1(3,0)*m2(0,0) + m1(3,1)*m2(1,0) +
1409  m1(3,2)*m2(2,0) + m1(3,3)*m2(3,0) ;
1410  m[3][1] = m1(3,0)*m2(0,1) + m1(3,1)*m2(1,1) +
1411  m1(3,2)*m2(2,1) + m1(3,3)*m2(3,1) ;
1412  m[3][2] = m1(3,0)*m2(0,2) + m1(3,1)*m2(1,2) +
1413  m1(3,2)*m2(2,2) + m1(3,3)*m2(3,2) ;
1414  m[3][3] = m1(3,0)*m2(0,3) + m1(3,1)*m2(1,3) +
1415  m1(3,2)*m2(2,3) + m1(3,3)*m2(3,3) ;
1416  return UT_Matrix4T<T>(m);
1417 }
1418 
1419 template <typename T, typename S>
1420 inline UT_Matrix4T<T>
1422 {
1423  T m[4][4];
1424  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1425  m[0][0] = m1(0,0) + x; m[0][1] = m1(0,1) + x;
1426  m[0][2] = m1(0,2) + x; m[0][3] = m1(0,3) + x;
1427 
1428  m[1][0] = m1(1,0) + y; m[1][1] = m1(1,1) + y;
1429  m[1][2] = m1(1,2) + y; m[1][3] = m1(1,3) + y;
1430 
1431  m[2][0] = m1(2,0) + z; m[2][1] = m1(2,1) + z;
1432  m[2][2] = m1(2,2) + z; m[2][3] = m1(2,3) + z;
1433 
1434  m[3][0] = m1(3,0) + w; m[3][1] = m1(3,1) + w;
1435  m[3][2] = m1(3,2) + w; m[3][3] = m1(3,3) + w;
1436  return UT_Matrix4T<T>(m);
1437 }
1438 
1439 template <typename T, typename S>
1440 inline UT_Matrix4T<T>
1441 operator+(const UT_Vector4T<S> &vec, const UT_Matrix4T<T> &mat)
1442 {
1443  return mat+vec;
1444 }
1445 
1446 template <typename T, typename S>
1447 inline UT_Matrix4T<T>
1449 {
1450  T m[4][4];
1451  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1452  m[0][0] = m1(0,0) - x; m[0][1] = m1(0,1) - x;
1453  m[0][2] = m1(0,2) - x; m[0][3] = m1(0,3) - x;
1454 
1455  m[1][0] = m1(1,0) - y; m[1][1] = m1(1,1) - y;
1456  m[1][2] = m1(1,2) - y; m[1][3] = m1(1,3) - y;
1457 
1458  m[2][0] = m1(2,0) - z; m[2][1] = m1(2,1) - z;
1459  m[2][2] = m1(2,2) - z; m[2][3] = m1(2,3) - z;
1460 
1461  m[3][0] = m1(3,0) - w; m[3][1] = m1(3,1) - w;
1462  m[3][2] = m1(3,2) - w; m[3][3] = m1(3,3) - w;
1463  return UT_Matrix4T<T>(m);
1464 }
1465 
1466 template <typename T, typename S>
1467 inline UT_Matrix4T<T>
1469 {
1470  T m[4][4];
1471  T x=vec.x(); T y=vec.y(); T z=vec.z(); T w=vec.w();
1472  m[0][0] = x - m1(0,0); m[0][1] = x - m1(0,1);
1473  m[0][2] = x - m1(0,2); m[0][3] = x - m1(0,3);
1474 
1475  m[1][0] = y - m1(1,0); m[1][1] = y - m1(1,1);
1476  m[1][2] = y - m1(1,2); m[1][3] = y - m1(1,3);
1477 
1478  m[2][0] = z - m1(2,0); m[2][1] = z - m1(2,1);
1479  m[2][2] = z - m1(2,2); m[2][3] = z - m1(2,3);
1480 
1481  m[3][0] = w - m1(3,0); m[3][1] = w - m1(3,1);
1482  m[3][2] = w - m1(3,2); m[3][3] = w - m1(3,3);
1483  return UT_Matrix4T<T>(m);
1484 }
1485 
1486 template <typename T, typename S>
1487 inline UT_Matrix4T<T>
1489 {
1490  T m[4][4];
1491  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;
1492  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;
1493  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;
1494  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;
1495  return UT_Matrix4T<T>(m);
1496 }
1497 
1498 template <typename T, typename S>
1499 inline UT_Matrix4T<T>
1501 {
1502  T m[4][4];
1503  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);
1504  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);
1505  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);
1506  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);
1507  return UT_Matrix4T<T>(m);
1508 }
1509 
1510 template <typename T, typename S>
1511 inline UT_Matrix4T<T>
1512 operator*(S sc, const UT_Matrix4T<T> &m1)
1513 {
1514  return m1*sc;
1515 }
1516 
1517 template <typename T, typename S>
1518 inline UT_Matrix4T<T>
1520 {
1521  T m[4][4];
1522  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;
1523  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;
1524  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;
1525  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;
1526  return UT_Matrix4T<T>(m);
1527 }
1528 
1529 template <typename T, typename S>
1530 inline
1532 operator/(const UT_Matrix4T<T> &m1, S scalar)
1533 {
1534  return (m1 * (1.0f/scalar));
1535 }
1536 
1537 template <typename T, typename S>
1538 inline UT_Matrix4T<T>
1540 {
1541  T m[4][4];
1542  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);
1543  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);
1544  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);
1545  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);
1546  return UT_Matrix4T<T>(m);
1547 }
1548 
1549 template <typename T>
1550 inline
1552 {
1553  return UT_Matrix4T<T>(
1554  SYSmin(v1(0,0), v2(0,0)),
1555  SYSmin(v1(0,1), v2(0,1)),
1556  SYSmin(v1(0,2), v2(0,2)),
1557  SYSmin(v1(0,3), v2(0,3)),
1558  SYSmin(v1(1,0), v2(1,0)),
1559  SYSmin(v1(1,1), v2(1,1)),
1560  SYSmin(v1(1,2), v2(1,2)),
1561  SYSmin(v1(1,3), v2(1,3)),
1562  SYSmin(v1(2,0), v2(2,0)),
1563  SYSmin(v1(2,1), v2(2,1)),
1564  SYSmin(v1(2,2), v2(2,2)),
1565  SYSmin(v1(2,3), v2(2,3)),
1566  SYSmin(v1(3,0), v2(3,0)),
1567  SYSmin(v1(3,1), v2(3,1)),
1568  SYSmin(v1(3,2), v2(3,2)),
1569  SYSmin(v1(3,3), v2(3,3))
1570  );
1571 }
1572 
1573 template <typename T>
1574 inline
1576 {
1577  return UT_Matrix4T<T>(
1578  SYSmax(v1(0,0), v2(0,0)),
1579  SYSmax(v1(0,1), v2(0,1)),
1580  SYSmax(v1(0,2), v2(0,2)),
1581  SYSmax(v1(0,3), v2(0,3)),
1582  SYSmax(v1(1,0), v2(1,0)),
1583  SYSmax(v1(1,1), v2(1,1)),
1584  SYSmax(v1(1,2), v2(1,2)),
1585  SYSmax(v1(1,3), v2(1,3)),
1586  SYSmax(v1(2,0), v2(2,0)),
1587  SYSmax(v1(2,1), v2(2,1)),
1588  SYSmax(v1(2,2), v2(2,2)),
1589  SYSmax(v1(2,3), v2(2,3)),
1590  SYSmax(v1(3,0), v2(3,0)),
1591  SYSmax(v1(3,1), v2(3,1)),
1592  SYSmax(v1(3,2), v2(3,2)),
1593  SYSmax(v1(3,3), v2(3,3))
1594  );
1595 }
1596 
1597 template <typename T,typename S>
1598 inline
1600 {
1601  return UT_Matrix4T<T>(
1602  SYSlerp(v1(0,0), v2(0,0), t),
1603  SYSlerp(v1(0,1), v2(0,1), t),
1604  SYSlerp(v1(0,2), v2(0,2), t),
1605  SYSlerp(v1(0,3), v2(0,3), t),
1606  SYSlerp(v1(1,0), v2(1,0), t),
1607  SYSlerp(v1(1,1), v2(1,1), t),
1608  SYSlerp(v1(1,2), v2(1,2), t),
1609  SYSlerp(v1(1,3), v2(1,3), t),
1610  SYSlerp(v1(2,0), v2(2,0), t),
1611  SYSlerp(v1(2,1), v2(2,1), t),
1612  SYSlerp(v1(2,2), v2(2,2), t),
1613  SYSlerp(v1(2,3), v2(2,3), t),
1614  SYSlerp(v1(3,0), v2(3,0), t),
1615  SYSlerp(v1(3,1), v2(3,1), t),
1616  SYSlerp(v1(3,2), v2(3,2), t),
1617  SYSlerp(v1(3,3), v2(3,3), t)
1618  );
1619 }
1620 
1621 template<typename T>
1623 {
1625  typedef T DataType;
1626  static const exint TupleSize = 16;
1627  static const bool isVectorType = true;
1628 };
1629 
1630 // Overload for custom formatting of UT_Matrix4T<T> with UTformat.
1631 template<typename T>
1632 UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix4T<T> &v);
1633 
1634 #endif
UT_Vector3T< T > myScaleOffset
Rotation pivot.
Definition: UT_Matrix4.h:742
void shear(T s_xy, T s_xz, T s_yz)
Definition: UT_Matrix4.h:588
void translate(const UT_Vector3T< T > &delta)
Definition: UT_Matrix4.h:620
void shear(const UT_Vector3T< T > &sh)
Definition: UT_Matrix4.h:602
Mat3< typename promote< S, T >::type > operator*(S scalar, const Mat3< T > &m)
Returns M, where for .
Definition: Mat3.h:615
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:432
#define SYS_STATIC_ASSERT(expr)
const UT_Vector4T< T > & operator[](unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix4.h:1209
bool operator!=(const UT_Matrix4T< T > &m) const
Definition: UT_Matrix4.h:285
SYS_FORCE_INLINE void prescale(T s)
Definition: UT_Matrix4.h:582
UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix4T< T > &v)
#define VM_STORE
Definition: VM_BasicFunc.h:328
T & z(void)
Definition: UT_Vector4.h:372
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:683
int myOrder
Definition: GT_CurveEval.h:263
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:715
const GLdouble * v
Definition: glcorearb.h:836
SYS_FORCE_INLINE T operator()(unsigned row, unsigned col) const
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix4.h:975
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Returns M, where for .
Definition: Mat3.h:631
UT_FixedVector< T, 16 > FixedVectorType
Definition: UT_Matrix4.h:1624
PivotSpaceT()
Constructor with default values for data members.
Definition: UT_Matrix4.h:677
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:969
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
UT_Matrix4T< T > & operator=(const UT_Matrix4T< S > &m)
Definition: UT_Matrix4.h:197
UT_Matrix4T< T > & operator*=(T scalar)
Definition: UT_Matrix4.h:303
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:471
void rotate(const UT_Vector3T< T > &rad, const UT_XformOrder &ord)
Definition: UT_Matrix4.h:529
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:72
#define UT_API
Definition: UT_API.h:12
GLint y
Definition: glcorearb.h:102
SYS_FORCE_INLINE void prescale(const UT_Vector3T< T > &s)
Definition: UT_Matrix4.h:580
Symmetric 4x4 Matrices.
Definition: UT_SymMatrix4.h:19
T trace() const
Definition: UT_Matrix4.h:387
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:741
UT_Vector3T< T > myRotateOffset
Translate.
Definition: UT_Matrix4.h:737
static const exint TupleSize
T determinant() const
Definition: UT_Matrix4.h:369
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:817
SYS_FORCE_INLINE T & x(void)
Definition: UT_Vector3.h:581
void prescale(T sx, T sy, T sz, T sw=1.0f)
Definition: UT_Matrix4.h:566
4D Vector class.
Definition: UT_Vector4.h:152
2D Vector class.
Definition: UT_Vector2.h:137
GLuint buffer
Definition: glcorearb.h:659
png_uint_32 i
Definition: png.h:2877
UT_Vector3T< S > myTranslate
Definition: UT_Matrix4.h:691
UT_Matrix4T< T > & operator-=(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:247
Define parameters for Houdini's pivot space.
Definition: UT_Matrix4.h:674
const T * data(void) const
Return the raw matrix data.
Definition: UT_Matrix4.h:959
void pretranslate(const UT_Vector3T< T > &delta)
Definition: UT_Matrix4.h:633
UT_Matrix4T< T > SYSmin(const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2)
Definition: UT_Matrix4.h:1551
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:101
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:73
PivotSpaceT< T > PivotSpace
Definition: UT_Matrix4.h:695
SYS_FORCE_INLINE T & z(void)
Definition: UT_Vector3.h:585
T myFloats[tuple_size]
Definition: UT_Matrix4.h:1042
GA_API const UT_StringHolder scale
GLdouble n
Definition: glcorearb.h:2007
static int entries()
Returns the vector size.
Definition: UT_Matrix4.h:1036
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:445
UT_Matrix4T< T > & operator=(const UT_Matrix3T< S > &m)
Definition: UT_Matrix4.h:183
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Returns M, where for .
Definition: Mat3.h:641
bool operator==(const UT_Matrix4T< T > &m) const
Definition: UT_Matrix4.h:269
int64 exint
Definition: SYS_Types.h:115
T coFactor(int k, int l) const
Definition: UT_Matrix4.h:344
void prerotate(const UT_Vector3T< T > &rad, const UT_XformOrder &ord)
Definition: UT_Matrix4.h:538
double fpreal64
Definition: SYS_Types.h:191
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:806
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:791
UT_Vector3T< T > myShear
Scale.
Definition: UT_Matrix4.h:744
void scale(T sx, T sy, T sz, T sw=1.0f)
Definition: UT_Matrix4.h:544
T determinant3() const
Compute determinant of the upper-left 3x3 sub-matrix.
Definition: UT_Matrix4.h:377
Definition: VM_SIMD.h:126
void pretranslate(T dx, T dy, T dz=0.0f)
Definition: UT_Matrix4.h:626
UT_Matrix4T< T > & operator+=(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:232
UT_Vector3T< T > myTranslate
transform and rotation order
Definition: UT_Matrix4.h:736
FullTransformModel()
Constructor with default values for data members.
Definition: UT_Matrix4.h:718
UT_Vector3T< T > myScale
Scale offset.
Definition: UT_Matrix4.h:743
int isZero() const
Definition: UT_Matrix4.h:942
int isIdentity() const
Definition: UT_Matrix4.h:928
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:426
void identity()
Set the matrix to identity.
Definition: UT_Matrix4.h:924
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:1575
UT_Vector3T< T > myRotate
Parent rotation (degrees, XYZ order)
Definition: UT_Matrix4.h:739
T & y(void)
Definition: UT_Vector4.h:370
const Vec2< S > & operator*=(Vec2< S > &v, const Matrix33< T > &m)
Definition: ImathMatrix.h:3330
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
UT_Vector3T< T > myParentRotate
Rotation offset.
Definition: UT_Matrix4.h:738
void lerp(const UT_Matrix4T< T > &a, const UT_Matrix4T< T > &b, T t)
Definition: UT_Matrix4.h:910
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:451
GA_API const UT_StringHolder orient
SYS_FORCE_INLINE const T * operator()(unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix4.h:991
void setTranslates(const UT_Vector3T< S > &translates)
Definition: UT_Matrix4.h:1200
UT_Matrix4T< T > & operator/=(T scalar)
Definition: UT_Matrix4.h:318
SYS_FORCE_INLINE void scale(const UT_Vector3T< T > &s)
Definition: UT_Matrix4.h:558
IFDmantra py
Definition: HDK_Image.dox:266
UT_Vector3T< S > myRotate
Definition: UT_Matrix4.h:692
T dot(unsigned i, unsigned j) const
Definition: UT_Matrix4.h:896
GLenum GLenum dst
Definition: glcorearb.h:1792
SYS_FORCE_INLINE T & y(void)
Definition: UT_Vector3.h:583
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:828
double fpreal
Definition: SYS_Types.h:269
Quaternion class.
Definition: UT_Quaternion.h:44
SYS_FORCE_INLINE T * operator()(unsigned row)
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix4.h:985
class UT_API UT_Matrix4T
UT_Matrix4T< T > operator-() const
Definition: UT_Matrix4.h:223
UT_Matrix4T< T > SYSlerp(const UT_Matrix4T< T > &v1, const UT_Matrix4T< T > &v2, S t)
Definition: UT_Matrix4.h:1599
SYS_FORCE_INLINE void scale(T s)
Definition: UT_Matrix4.h:560
GA_API const UT_StringHolder up
T getEuclideanNorm() const
Definition: UT_Matrix4.h:1004
UT_Vector3T< T > myPivotRotate
Overall pivot.
Definition: UT_Matrix4.h:747
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:102
UT_Vector3T< T > myScalePivot
Shear (within scale pivot)
Definition: UT_Matrix4.h:745
void zero()
Set the matrix to zero.
Definition: UT_Matrix4.h:926
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:212
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:823
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:459
T & x(void)
Definition: UT_Vector4.h:368
#define SYS_FTOLERANCE
Definition: SYS_Types.h:202
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
void leftMult(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:1311
UT_Matrix4T< T > operator/(const UT_Matrix4T< T > &mat, S sc)
Definition: UT_Matrix4.h:1532
UT_Vector3T< T > myChildRotate
Rotation (degrees, myOrder order)
Definition: UT_Matrix4.h:740
GLboolean r
Definition: glcorearb.h:1221
UT_Vector3T< T > myPivot
Scale pivot.
Definition: UT_Matrix4.h:746
PivotSpaceT(const UT_Vector3T< S > &translate, const UT_Vector3T< S > &rotate)
Convenience constructor with translate and rotate.
Definition: UT_Matrix4.h:684
T & w(void)
Definition: UT_Vector4.h:374
T matx[4][4]
Definition: UT_Matrix4.h:1041
void translate(T dx, T dy, T dz=0.0f)
Definition: UT_Matrix4.h:608
v4sf vector
Definition: VM_SIMD.h:271
int explode(const UT_XformOrder &order, UT_Vector3D &r, UT_Vector3D &s, UT_Vector3D &t, UT_Vector3D *shears=0) const
Definition: UT_Matrix4.h:795
UT_Matrix4T< T > & operator*=(const UT_Matrix4T< S > &m)
Definition: UT_Matrix4.h:1226
T * data(void)
Return the raw matrix data.
Definition: UT_Matrix4.h:960
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:811
void getTranslates(UT_Vector3T< S > &translates) const
Definition: UT_Matrix4.h:1190
void preMultiply(const UT_Matrix4T< T > &m)
Definition: UT_Matrix4.h:338
unsigned hash() const
Compute a hash.
Definition: UT_Matrix4.h:964