HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
UT_Matrix3.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_Matrix3_h__
11 #define __UT_Matrix3_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_Swap.h"
18 #include "UT_SymMatrix3.h"
19 #include "UT_VectorTypes.h"
20 
21 #include <SYS/SYS_Deprecated.h>
22 #include <SYS/SYS_Math.h>
23 #include <iosfwd>
24 
25 class UT_IStream;
26 class UT_JSONParser;
27 class UT_JSONWriter;
28 class UT_JSONValue;
29 
30 // Free floating operators that return a UT_Matrix3T object.
31 template <typename T>
33 template <typename T>
35 template <typename T>
37 template <typename T, typename S>
39 template <typename T, typename S>
40 inline UT_Matrix3T<T> operator+(const UT_Vector3T<S> &v, const UT_Matrix3T<T> &m);
41 template <typename T, typename S>
43 template <typename T, typename S>
45 template <typename T, typename S>
47 template <typename T, typename S>
48 inline UT_Matrix3T<T> operator-(const UT_Matrix3T<T> &mat, S sc);
49 template <typename T, typename S>
51 template <typename T, typename S>
52 inline UT_Matrix3T<T> operator/(const UT_Matrix3T<T> &mat, S sc);
53 template <typename T, typename S>
54 inline UT_Matrix3T<T> operator+(S sc, const UT_Matrix3T<T> &mat);
55 template <typename T, typename S>
57 template <typename T, typename S>
58 inline UT_Matrix3T<T> operator*(S sc, const UT_Matrix3T<T> &mat);
59 template <typename T, typename S>
61 
62 template <typename T>
63 inline UT_Matrix3T<T> SYSmin (const UT_Matrix3T<T> &v1, const UT_Matrix3T<T> &v2);
64 template <typename T>
65 inline UT_Matrix3T<T> SYSmax (const UT_Matrix3T<T> &v1, const UT_Matrix3T<T> &v2);
66 template <typename T,typename S>
67 inline UT_Matrix3T<T> SYSlerp(const UT_Matrix3T<T> &v1, const UT_Matrix3T<T> &v2, S t);
68 template <typename T,typename S>
69 inline UT_Matrix3T<T> SYSbilerp(const UT_Matrix3T<T> &u0v0, const UT_Matrix3T<T> &u1v0,
70  const UT_Matrix3T<T> &u0v1, const UT_Matrix3T<T> &u1v1,
71  S u, S v)
72 { return SYSlerp(SYSlerp(u0v0, u0v1, v), SYSlerp(u1v0, u1v1, v), u); }
73 
74 /// This class implements a 3x3 float matrix in row-major order.
75 ///
76 /// Most of Houdini operates with row vectors that are left-multiplied with
77 /// matrices. e.g., z = v * M
78 ///
79 /// This convention, combined with row-major order, is directly compatible
80 /// with OpenGL matrix requirements.
81 template <typename T>
83 {
84 public:
85 
86  typedef T value_type;
87  static const int tuple_size = 9;
88 
89  /// Construct uninitialized matrix.
90  SYS_FORCE_INLINE UT_Matrix3T() = default;
91 
92  /// Default copy constructor
93  constexpr UT_Matrix3T(const UT_Matrix3T &) = default;
94 
95  /// Default move constructor
96  constexpr UT_Matrix3T(UT_Matrix3T &&) = default;
97 
98  /// Construct identity matrix, multipled by scalar.
99  explicit constexpr UT_Matrix3T(fpreal64 val) noexcept
100  : matx{{T(val),0,0},{0,T(val),0},{0,0,T(val)}}
101  {
102  SYS_STATIC_ASSERT(sizeof(UT_Matrix3T<T>) == tuple_size * sizeof(T));
103  }
104  /// Construct a deep copy of the input row-major data.
105  /// @{
106  template <typename S>
107  explicit constexpr UT_Matrix3T(const S m[3][3]) noexcept
108  : matx{
109  {T(m[0][0]),T(m[0][1]),T(m[0][2])},
110  {T(m[1][0]),T(m[1][1]),T(m[1][2])},
111  {T(m[2][0]),T(m[2][1]),T(m[2][2])}}
112  {}
113  /// @}
114 
115  /// Arbitrary UT_FixedVector of the same size
116  template <typename S,bool INST>
118  : matx{
119  {v[0],v[1],v[2]},
120  {v[3],v[4],v[5]},
121  {v[6],v[7],v[8]}}
122  {}
123 
124  /// Construct from 3 row vectors
125  template <typename S,bool INST>
127  const UT_FixedVector<S,3,INST> &r0,
128  const UT_FixedVector<S,3,INST> &r1,
129  const UT_FixedVector<S,3,INST> &r2) noexcept
130  : matx{
131  {r0[0],r0[1],r0[2]},
132  {r1[0],r1[1],r1[2]},
133  {r2[0],r2[1],r2[2]}}
134  {}
135 
136  /// This constructor is for convenience.
137  constexpr UT_Matrix3T(
138  T val00, T val01, T val02,
139  T val10, T val11, T val12,
140  T val20, T val21, T val22) noexcept
141  : matx{
142  {val00,val01,val02},
143  {val10,val11,val12},
144  {val20,val21,val22}}
145  {}
146 
147  /// Base type conversion constructor
148  template <typename S>
149  UT_Matrix3T(const UT_Matrix3T<S> &m) noexcept
150  : matx{
151  {T(m(0,0)),T(m(0,1)),T(m(0,2))},
152  {T(m(1,0)),T(m(1,1)),T(m(1,2))},
153  {T(m(2,0)),T(m(2,1)),T(m(2,2))}}
154  {}
155  explicit UT_Matrix3T(const UT_Matrix4T<fpreal32> &m);
156  explicit UT_Matrix3T(const UT_Matrix4T<fpreal64> &m);
157 
158  /// Construct from a symmetric 3x3 matrix
159  template <typename S>
160  explicit UT_Matrix3T(const UT_SymMatrix3T<S> m)
161  {
162  this->operator=(m);
163  }
164 
165  /// Default copy assignment operator
166  UT_Matrix3T<T> &operator=(const UT_Matrix3T<T> &m) = default;
167 
168  /// Default move assignment operator
169  UT_Matrix3T<T> &operator=(UT_Matrix3T<T> &&m) = default;
170 
171  /// Conversion operator that returns a 3x3 from a 4x4 matrix by ignoring the
172  /// last row and last column.
173  /// @{
174  UT_Matrix3T<T> &operator=(const UT_Matrix4T<fpreal32> &m);
175  UT_Matrix3T<T> &operator=(const UT_Matrix4T<fpreal64> &m);
176  /// @}
177  template <typename S>
179  {
180  matx[0][0]=m(0,0); matx[0][1]=m(0,1); matx[0][2]=m(0,2);
181  matx[1][0]=m(1,0); matx[1][1]=m(1,1); matx[1][2]=m(1,2);
182  matx[2][0]=m(2,0); matx[2][1]=m(2,1); matx[2][2]=m(2,2);
183  return *this;
184  }
185 
186  /// Convert from a symmetric matrix to non-symmetric.
187  template <typename S>
189  {
190  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
191  const LowerTri &l = m.lowerTri();
192  matx[0][0] = l.q00; matx[0][1] = l.q10; matx[0][2] = l.q20;
193  matx[1][0] = l.q10; matx[1][1] = l.q11; matx[1][2] = l.q21;
194  matx[2][0] = l.q20; matx[2][1] = l.q21; matx[2][2] = l.q22;
195  return *this;
196  }
197 
198  /// Convert this to a symmetric matrix, using the lower-triangular portion
200  {
201  return UT_SymMatrix3T<T>(matx[0][0],
202  matx[1][0], matx[1][1],
203  matx[2][0], matx[2][1], matx[2][2]);
204  }
205 
206  /// Convert this to a symmetric matrix, using the upper-triangular portion
208  {
209  return UT_SymMatrix3T<T>(matx[0][0],
210  matx[0][1], matx[1][1],
211  matx[0][2], matx[1][2], matx[2][2]);
212  }
213 
214  /// Convert this to a symmetric matrix, using averaged components
216  {
217  return UT_SymMatrix3T<T>(matx[0][0],
218  (matx[0][1] + matx[1][0]) / 2,
219  matx[1][1],
220  (matx[0][2] + matx[2][0]) / 2,
221  (matx[1][2] + matx[2][1]) / 2,
222  matx[2][2]);
223  }
224 
226  {
227  return UT_Matrix3T<T>(-matx[0][0], -matx[0][1], -matx[0][2],
228  -matx[1][0], -matx[1][1], -matx[1][2],
229  -matx[2][0], -matx[2][1], -matx[2][2]);
230  }
231 
232  // Does += k * m
233  inline void addScaledMat(T k, const UT_Matrix3T<T> &m)
234  {
235  matx[0][0]+=k*m.matx[0][0];
236  matx[0][1]+=k*m.matx[0][1];
237  matx[0][2]+=k*m.matx[0][2];
238 
239  matx[1][0]+=k*m.matx[1][0];
240  matx[1][1]+=k*m.matx[1][1];
241  matx[1][2]+=k*m.matx[1][2];
242 
243  matx[2][0]+=k*m.matx[2][0];
244  matx[2][1]+=k*m.matx[2][1];
245  matx[2][2]+=k*m.matx[2][2];
246  }
248  {
249  matx[0][0]+=m.matx[0][0];
250  matx[0][1]+=m.matx[0][1];
251  matx[0][2]+=m.matx[0][2];
252 
253  matx[1][0]+=m.matx[1][0];
254  matx[1][1]+=m.matx[1][1];
255  matx[1][2]+=m.matx[1][2];
256 
257  matx[2][0]+=m.matx[2][0];
258  matx[2][1]+=m.matx[2][1];
259  matx[2][2]+=m.matx[2][2];
260  return *this;
261  }
263  {
264  matx[0][0]-=m.matx[0][0];
265  matx[0][1]-=m.matx[0][1];
266  matx[0][2]-=m.matx[0][2];
267 
268  matx[1][0]-=m.matx[1][0];
269  matx[1][1]-=m.matx[1][1];
270  matx[1][2]-=m.matx[1][2];
271 
272  matx[2][0]-=m.matx[2][0];
273  matx[2][1]-=m.matx[2][1];
274  matx[2][2]-=m.matx[2][2];
275  return *this;
276  }
278 
279  /// Multiply given symmetric matrix on the right
280  template <typename S>
282  {
283  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
284 
285  const LowerTri& l = m.lowerTri();
286  T a, b, c;
287 
288  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
289  matx[0][0] = a*l.q00 + b*l.q10 + c*l.q20;
290  matx[0][1] = a*l.q10 + b*l.q11 + c*l.q21;
291  matx[0][2] = a*l.q20 + b*l.q21 + c*l.q22;
292 
293  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
294  matx[1][0] = a*l.q00 + b*l.q10 + c*l.q20;
295  matx[1][1] = a*l.q10 + b*l.q11 + c*l.q21;
296  matx[1][2] = a*l.q20 + b*l.q21 + c*l.q22;
297 
298  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
299  matx[2][0] = a*l.q00 + b*l.q10 + c*l.q20;
300  matx[2][1] = a*l.q10 + b*l.q11 + c*l.q21;
301  matx[2][2] = a*l.q20 + b*l.q21 + c*l.q22;
302 
303  return *this;
304  }
305 
306  /// Multiply given symmetric matrix on the left
307  template <typename S>
309  {
310  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
311 
312  const LowerTri& l = m.lowerTri();
313  T a, b, c;
314 
315  a = matx[0][0]; b = matx[1][0]; c = matx[2][0];
316  matx[0][0] = a*l.q00 + b*l.q10 + c*l.q20;
317  matx[1][0] = a*l.q10 + b*l.q11 + c*l.q21;
318  matx[2][0] = a*l.q20 + b*l.q21 + c*l.q22;
319 
320  a = matx[0][1]; b = matx[1][1]; c = matx[2][1];
321  matx[0][1] = a*l.q00 + b*l.q10 + c*l.q20;
322  matx[1][1] = a*l.q10 + b*l.q11 + c*l.q21;
323  matx[2][1] = a*l.q20 + b*l.q21 + c*l.q22;
324 
325  a = matx[0][2]; b = matx[1][2]; c = matx[2][2];
326  matx[0][2] = a*l.q00 + b*l.q10 + c*l.q20;
327  matx[1][2] = a*l.q10 + b*l.q11 + c*l.q21;
328  matx[2][2] = a*l.q20 + b*l.q21 + c*l.q22;
329  }
330 
331  /// Multiply given matrix3 on the left
332  template <typename S>
333  void leftMult(const UT_Matrix3T<S> &m)
334  {
335  T a, b, c;
336 
337  a = matx[0][0]; b = matx[1][0]; c = matx[2][0];
338  matx[0][0] = a*m(0,0) + b*m(0,1) + c*m(0,2);
339  matx[1][0] = a*m(1,0) + b*m(1,1) + c*m(1,2);
340  matx[2][0] = a*m(2,0) + b*m(2,1) + c*m(2,2);
341 
342  a = matx[0][1]; b = matx[1][1]; c = matx[2][1];
343  matx[0][1] = a*m(0,0) + b*m(0,1) + c*m(0,2);
344  matx[1][1] = a*m(1,0) + b*m(1,1) + c*m(1,2);
345  matx[2][1] = a*m(2,0) + b*m(2,1) + c*m(2,2);
346 
347  a = matx[0][2]; b = matx[1][2]; c = matx[2][2];
348  matx[0][2] = a*m(0,0) + b*m(0,1) + c*m(0,2);
349  matx[1][2] = a*m(1,0) + b*m(1,1) + c*m(1,2);
350  matx[2][2] = a*m(2,0) + b*m(2,1) + c*m(2,2);
351  }
352 
353  void multiply3(const UT_Matrix4 &m);
354  void multiply3(const UT_DMatrix4 &m);
355 
356  constexpr bool operator==(const UT_Matrix3T<T> &m) const noexcept
357  {
358  return (&m == this) || (
359  matx[0][0]==m(0,0) && matx[0][1]==m(0,1) && matx[0][2]==m(0,2) &&
360  matx[1][0]==m(1,0) && matx[1][1]==m(1,1) && matx[1][2]==m(1,2) &&
361  matx[2][0]==m(2,0) && matx[2][1]==m(2,1) && matx[2][2]==m(2,2) );
362  }
363  constexpr bool operator!=(const UT_Matrix3T<T> &m) const noexcept
364  {
365  return !(*this == m);
366  }
367 
368  // Scalar operators:
369  UT_Matrix3T<T> &operator= (T val)
370  {
371  matx[0][0] = val; matx[0][1] = 0; matx[0][2] = 0;
372  matx[1][0] = 0; matx[1][1] = val; matx[1][2] = 0;
373  matx[2][0] = 0; matx[2][1] = 0; matx[2][2] = val;
374  return *this;
375  }
376  inline UT_Matrix3T<T> &operator*=(T scalar)
377  {
378  matx[0][0]*=scalar; matx[0][1]*=scalar; matx[0][2]*=scalar;
379  matx[1][0]*=scalar; matx[1][1]*=scalar; matx[1][2]*=scalar;
380  matx[2][0]*=scalar; matx[2][1]*=scalar; matx[2][2]*=scalar;
381  return *this;
382  }
383  inline UT_Matrix3T<T> &operator/=(T scalar)
384  {
385  return operator*=( 1.0f/scalar );
386  }
387 
388  // Vector3 operators:
389  template <typename S>
390  inline UT_Matrix3T<T> &operator= (const UT_Vector3T<S> &vec);
391  template <typename S>
392  inline UT_Matrix3T<T> &operator+=(const UT_Vector3T<S> &vec);
393  template <typename S>
394  inline UT_Matrix3T<T> &operator-=(const UT_Vector3T<S> &vec);
395 
396  /// Scaled outer product update (given scalar b, row vectors v1 and v2)
397  /// this += b * transpose(v1) * v2
398  /// @{
399  template <typename S>
400  inline void outerproductUpdateT(T b,
401  const UT_Vector3T<S> &v1,
402  const UT_Vector3T<S> &v2);
403  inline void outerproductUpdate(T b,
404  const UT_Vector3F &v1,
405  const UT_Vector3F &v2)
406  { outerproductUpdateT(b, v1, v2); }
407  inline void outerproductUpdate(T b,
408  const UT_Vector3D &v1,
409  const UT_Vector3D &v2)
410  { outerproductUpdateT(b, v1, v2); }
411  /// @}
412 
413  // Other matrix operations:
414  // Computes the basis of a 3x3 matrix. This is used by OBB code
415  // to determine what orientation of a bounding box best represents
416  // a cloud of points. To do this, first fill this matrix with
417  // the sum of p*pT for all points in the cloud.
418  // The result is in this matrix itself.
419  void getBasis();
420 
421  // Sets this matrix to the canonical 180 rotation matrix (about the y axis)
422  // that is used in the orient() and dihedral() functions when given two
423  // opposing vectors.
424  void arbitrary180rot();
425 
426  /// Compute the dihedral: return the matrix that computes the rotation
427  /// around the axes normal to both a and b, (their cross product), by the
428  /// angle which is between a and b. The resulting matrix maps a onto b. If
429  /// a and b have the same direction, what comes out is the identity matrix.
430  /// If a and b are opposed, the rotation is undefined and the method
431  /// returns a vector c of zeroes (check with !c); if all is OK, c != 0.
432  /// The transformation is a symmetry around vector a, then a symmetry
433  /// around (norm(a) and norm(b)). If a or b needs to be normalized, pass a
434  /// non-zero value in norm.
435  /// The second function places the result in 'm', and returns 0 if a and b
436  /// are not opposed; otherwise, it returns 1.
437  // @{
438  template <typename S>
439  static UT_Matrix3T<T> dihedral(UT_Vector3T<S> &a, UT_Vector3T<S> &b,
440  UT_Vector3T<S> &c,int norm=1);
441  /// @note If dihedral() returns 0, this matrix is NOT modified!
442  template <typename S>
443  int dihedral(UT_Vector3T<S> &a, UT_Vector3T<S> &b,
444  int norm=1);
445  // @}
446 
447  // Compute a lookat matrix: These functions will compute a rotation matrix
448  // (yes, with all the properties of a rotation matrix), which will provide
449  // the rotates needed for "from" to look at "to". One method uses a "roll"
450  // the other method uses an "up" vector to determine the orientation. The
451  // "roll" is not as well defined as using an "up" vector. If the two points
452  // are co-incident, the result will be an identity matrix. If norm is set,
453  // then the up vector will be normalized.
454  // The lookat matrix will have the -Z axis pointing at the "to" point.
455  // The y axis will be pointing "up"
456  template <typename S>
457  void lookat(const UT_Vector3T<S> &from, const UT_Vector3T<S> &to,
458  T roll = 0);
459  template <typename S>
460  void lookat(const UT_Vector3T<S> &from, const UT_Vector3T<S> &to,
461  const UT_Vector3T<S> &up);
462 
463 
464  // Compute the transform matrix to orient given a direction and an up vector
465  // If the direction and up are not orthogonal, then the up vector will be
466  // shifted along the direction to make it orthogonal... If the up and
467  // direction vectors are co-linear, then an identity matrix will be
468  // returned.
469  // The second function will return 0 to indicate this. The inputs may
470  // be modified by the orient functions.
471  template <typename S>
472  int orient(UT_Vector3T<S> &dir, UT_Vector3T<S> &up, int norm=1);
473  template <typename S>
474  int orientInverse(UT_Vector3T<S> &dir, UT_Vector3T<S> &up, int norm=1);
475 
476 
477  // Computes a transform to orient to a given direction (v) with a scale
478  // (pscale). The up vector (up) is optional and will orient the matrix to
479  // this up vector. If no up vector is given, the z axis will be oriented to
480  // point in the v direction. If a quaternion (q) is specified, the
481  // orientation will be additionally transformed by the rotation specified
482  // by the quaternion.
483  // The matrix is scaled non-uniformly about each axis using s3, if s3
484  // is non-zero. A uniform scale of pscale is applied regardless, so if
485  // s3 is non-zero, the x axis will be scaled by pscale * s3->x().
486  template <typename S>
487  void orientT(const UT_Vector3T<S>& v,
488  T pscale, const UT_Vector3T<S> *s3,
489  const UT_Vector3T<S>* up,
490  const UT_QuaternionT<S> * q);
491  void orient(const UT_Vector3F &v,
492  T pscale, const UT_Vector3F *s3,
493  const UT_Vector3F *up,
494  const UT_QuaternionF *q)
495  { orientT(v, pscale, s3, up, q); }
496  void orient(const UT_Vector3D &v,
497  T pscale, const UT_Vector3D *s3,
498  const UT_Vector3D *up,
499  const UT_QuaternionD *q)
500  { orientT(v, pscale, s3, up, q); }
501  template <typename S>
502  void orientInverseT(const UT_Vector3T<S>& v,
503  T pscale, const UT_Vector3T<S> *s3,
504  const UT_Vector3T<S>* up,
505  const UT_QuaternionT<S> * q);
507  T pscale, const UT_Vector3F *s3,
508  const UT_Vector3F *up,
509  const UT_QuaternionF *q)
510  { orientInverseT(v, pscale, s3, up, q); }
512  T pscale, const UT_Vector3D *s3,
513  const UT_Vector3D *up,
514  const UT_QuaternionD *q)
515  { orientInverseT(v, pscale, s3, up, q); }
516 
517  // Return the cofactor of the matrix, ie the determinant of the 2x2
518  // submatrix that results from removing row 'k' and column 'l' from the
519  // 3x3.
520  inline T coFactor(int k, int l) const
521  {
522  int r[2], c[2];
523 
524  // r, c should evaluate to compile time constants
525  coVals(k, r);
526  coVals(l, c);
527  if ((k ^ l) & 1)
528  UTswap(c[0], c[1]);
529 
530  return matx[r[0]][c[0]]*matx[r[1]][c[1]] -
531  matx[r[0]][c[1]]*matx[r[1]][c[0]];
532  }
533 
534  T determinant() const
535  {
536  return(matx[0][0]*coFactor(0,0) +
537  matx[0][1]*coFactor(0,1) +
538  matx[0][2]*coFactor(0,2));
539  }
540  T trace() const
541  { return matx[0][0] + matx[1][1] + matx[2][2]; }
542 
543  /// Computes the eigenvalues. Returns number of real eigenvalues
544  /// found. Uses UT_RootFinder::cubic
545  /// @param r The real eigenvalues
546  /// @param i The imaginary eigenvalues
547  template <typename S>
548  int eigenvalues(UT_Vector3T<S> &r, UT_Vector3T<S> &i) const;
549 
550  /// Invert this matrix and return 0 if OK, 1 if singular.
551  int invert();
552  /// Invert the matrix and return 0 if OK, 1 if singular.
553  /// Puts the inverted matrix in m, and leaves this matrix unchanged.
554  int invert(UT_Matrix3T<T> &m)const;
555 
556  /// Use Kramer's method to compute the matrix inverse
557  /// If abs( det(m) ) <= abs_det_threshold, then return 1 without changing m
558  /// Otherwise, return 0, storing the inverse matrix in m
559  ///
560  /// NOTE: The default FLT_EPSILON is kept here to preserve existing behavior
561  /// This is not a good default!
562  /// The right threshold must be decided separately for each use case.
563  int invertKramer(UT_Matrix3T<T> &m, T abs_det_threshold = FLT_EPSILON) const;
564 
565  // Shorthand for invertKramer(*this)
566  int invertKramer(T abs_det_threshold = FLT_EPSILON);
567 
568  // Invert *this.
569  // *this should be symmetric.
570  // *this does NOT have to be non-singular. Singular matrices will be
571  // inverted by filtering out the singular component.
572  // This means you can reliably solve:
573  // M x = b
574  // for the x that is closest to satisfying b
575  // Returns 0 on success, 1 if something really bad happened.
576  int safeInvertSymmetric(T tol=1e-6f);
577 
578  // Diagonalize *this.
579  // *this should be symmetric.
580  // The matrix is factored into:
581  // *this = Rt D R
582  // The diagonalization is done with a serios of jacobi rotations.
583  // *this is unchanged by the operations.
584  // Returns true if successful, false if reached maximum iterations rather
585  // than desired tolerance.
586  // Tolerance is with respect to the maximal element of the matrix.
587  bool diagonalizeSymmetric(UT_Matrix3T<T> &R, UT_Matrix3T<T> &D, T tol=1e-6f, int maxiter = 100) const;
588 
589  // Compute the SVD decomposition of *this
590  // The matrix is factored into
591  // *this = U * S * Vt
592  // Where S is diagonal, and U and Vt are both orthognal matrices
593  // Tolerance is with respect to the maximal element of the matrix
594  void svdDecomposition(UT_Matrix3T<T> &U, UT_Matrix3T<T> &S, UT_Matrix3T<T> &V, T tol=1e-6f) const;
595 
596  /// Splits a covariance matrix into a scale & rotation component.
597  /// This should be built by a series of outer product updates.
598  /// R is the rotation component, S the inverse scale.
599  /// If this is A, finds the inverse square root of AtA, S.
600  /// We then set R = transpose(AS) to give us a rotation matrix.
601  /// NOTE: For general matrices, use makeRotationMatrix()!
602  void splitCovarianceToRotationScale(UT_Matrix3T<T> &R, UT_Matrix3T<T> &S, T tol=1e-6f) const;
603 
604  bool isSymmetric(T tolerance = T(SYS_FTOLERANCE)) const;
605 
606  // Transpose this matrix or return its transpose.
607  void transpose(void)
608  {
609  T tmp;
610  tmp=matx[0][1]; matx[0][1]=matx[1][0]; matx[1][0]=tmp;
611  tmp=matx[0][2]; matx[0][2]=matx[2][0]; matx[2][0]=tmp;
612  tmp=matx[1][2]; matx[1][2]=matx[2][1]; matx[2][1]=tmp;
613  }
615  {
616  return UT_Matrix3T<T>(matx[0][0], matx[1][0], matx[2][0],
617  matx[0][1], matx[1][1], matx[2][1],
618  matx[0][2], matx[1][2], matx[2][2]);
619  }
621  { return transposedCopy(); }
622 
623  // check for equality within a tolerance level
624  bool isEqual( const UT_Matrix3T<T> &m,
625  T tolerance=T(SYS_FTOLERANCE) ) const
626  {
627  return (&m == this) || (
628  SYSisEqual( matx[0][0], m.matx[0][0], tolerance ) &&
629  SYSisEqual( matx[0][1], m.matx[0][1], tolerance ) &&
630  SYSisEqual( matx[0][2], m.matx[0][2], tolerance ) &&
631 
632  SYSisEqual( matx[1][0], m.matx[1][0], tolerance ) &&
633  SYSisEqual( matx[1][1], m.matx[1][1], tolerance ) &&
634  SYSisEqual( matx[1][2], m.matx[1][2], tolerance ) &&
635 
636  SYSisEqual( matx[2][0], m.matx[2][0], tolerance ) &&
637  SYSisEqual( matx[2][1], m.matx[2][1], tolerance ) &&
638  SYSisEqual( matx[2][2], m.matx[2][2], tolerance ) );
639  }
640 
641  /// Post-multiply this matrix by a 3x3 rotation matrix determined by the
642  /// axis and angle of rotation in radians.
643  /// If 'norm' is not 0, the axis vector is normalized before computing the
644  /// rotation matrix. rotationMat() returns a rotation matrix, and could as
645  /// well be defined as a free floating function.
646  /// @{
647  template <typename S>
648  void rotate(UT_Vector3T<S> &axis, T theta, int norm=1);
649  void rotate(UT_Axis3::axis a, T theta);
650  template <typename S>
651  SYS_DEPRECATED(12.0) UT_Matrix3T<T> rotate(UT_Vector3T<S> &axis, T theta, int norm=1) const;
652  SYS_DEPRECATED(12.0) UT_Matrix3T<T> rotate(UT_Axis3::axis a, T theta) const;
653  /// @}
654 
655  /// Create a rotation matrix for the given angle in radians around the axis
656  /// @{
657  template <typename S>
658  static UT_Matrix3T<T> rotationMat(UT_Vector3T<S> &axis, T theta, int norm=1);
659  static UT_Matrix3T<T> rotationMat(UT_Axis3::axis a, T theta);
660  /// @}
661 
662  /// Pre-multiply this matrix by the theta radians rotation around the axis
663  /// @{
664  template <typename S>
665  void prerotate(UT_Vector3T<S> &axis, T theta, int norm=1);
666  void prerotate(UT_Axis3::axis a, T theta);
667  template <typename S>
668  SYS_DEPRECATED(12.0) UT_Matrix3T<T> prerotate(UT_Vector3T<S> &axis, T theta, int norm=1) const;
669  SYS_DEPRECATED(12.0) UT_Matrix3T<T> prerotate(UT_Axis3::axis a, T theta) const;
670  /// @}
671 
672  /// Pre-rotate by rx, ry, rz radians around the three basic axes in the
673  /// order given by UT_XformOrder.
674  /// @{
675  void prerotate(T rx, T ry, T rz,
676  const UT_XformOrder &order);
677  inline void prerotate(const UT_Vector3T<T> &rad, const UT_XformOrder &order)
678  { prerotate(rad(0), rad(1), rad(2), order); }
679  SYS_DEPRECATED(12.0) UT_Matrix3T<T> prerotate(T rx, T ry, T rz,
680  const UT_XformOrder &order) const;
681  /// @}
682 
683 
684  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
685  /// order given by UT_XformOrder.
686  /// @{
687  void rotate(T rx, T ry, T rz,
688  const UT_XformOrder &ord);
689  inline void rotate(const UT_Vector3T<T> &rad, const UT_XformOrder &ord)
690  { rotate(rad(0), rad(1), rad(2), ord); }
691  SYS_DEPRECATED(12.0) UT_Matrix3T<T> rotate(T rx, T ry, T rz,
692  const UT_XformOrder &ord) const;
693  /// @}
694 
695  /// Post-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
696  /// @{
697  void scale(T sx, T sy, T sz)
698  {
699  matx[0][0] *= sx; matx[0][1] *= sy; matx[0][2] *= sz;
700  matx[1][0] *= sx; matx[1][1] *= sy; matx[1][2] *= sz;
701  matx[2][0] *= sx; matx[2][1] *= sy; matx[2][2] *= sz;
702  }
703  inline void scale(const UT_Vector3T<T> &s)
704  { scale(s(0), s(1), s(2)); }
705  SYS_DEPRECATED(12.0) UT_Matrix3T<T> scale(T sx, T sy, T sz) const;
706  /// @}
707 
708  /// Pre-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
709  /// @{
710  void prescale(T sx, T sy, T sz)
711  {
712  matx[0][0] *= sx; matx[1][0] *= sy; matx[2][0] *= sz;
713  matx[0][1] *= sx; matx[1][1] *= sy; matx[2][1] *= sz;
714  matx[0][2] *= sx; matx[1][2] *= sy; matx[2][2] *= sz;
715  }
716  inline void prescale(const UT_Vector3T<T> &s)
717  { prescale(s(0), s(1), s(2)); }
718  SYS_DEPRECATED(12.0) UT_Matrix3T<T> prescale(T sx, T sy, T sz) const;
719  /// @}
720 
721  /// Negates this matrix, i.e. multiplies it by -1.
722  SYS_FORCE_INLINE void negate()
723  {
724  matx[0][0] = -matx[0][0]; matx[0][1] = -matx[0][1]; matx[0][2] = -matx[0][2];
725  matx[1][0] = -matx[1][0]; matx[1][1] = -matx[1][1]; matx[1][2] = -matx[1][2];
726  matx[2][0] = -matx[2][0]; matx[2][1] = -matx[2][1]; matx[2][2] = -matx[2][2];
727  }
728 
729  /// Post-multiply this matrix by a translation matrix determined by (dx,dy)
730  /// @{
731  void translate(T dx, T dy)
732  {
733  matx[0][0] += matx[0][2] * dx;
734  matx[0][1] += matx[0][2] * dy;
735  matx[1][0] += matx[1][2] * dx;
736  matx[1][1] += matx[1][2] * dy;
737  matx[2][0] += matx[2][2] * dx;
738  matx[2][1] += matx[2][2] * dy;
739  }
740  inline void translate(const UT_Vector2T<T> &delta)
741  { translate(delta(0), delta(1)); }
742  SYS_DEPRECATED(12.0) UT_Matrix3T<T> translate(T dx, T dy) const;
743  /// @}
744 
745  /// Pre-multiply this matrix by the translation matrix determined by (dx,dy)
746  /// @{
747  void pretranslate(T dx, T dy)
748  {
749  matx[2][0] += matx[0][0] * dx + matx[1][0] * dy;
750  matx[2][1] += matx[0][1] * dx + matx[1][1] * dy;
751  matx[2][2] += matx[0][2] * dx + matx[1][2] * dy;
752  }
753  inline void pretranslate(const UT_Vector2T<T> &delta)
754  { pretranslate(delta(0), delta(1)); }
755  SYS_DEPRECATED(12.0) UT_Matrix3T<T> pretranslate(T dx, T dy) const;
756  /// @}
757 
758  /// Generate the x, y, and z values of rotation in radians.
759  /// Return 0 if successful, and a non-zero value otherwise: 1 if the matrix
760  /// is not a valid rotation matrix, 2 if rotOrder is invalid, and 3 for
761  /// other errors. rotOrder must be given as a UT_XformOrder permulation.
762  /// WARNING: For animation or transform blending, use polarDecompose()
763  /// or makeRotationMatrix()!
764  /// WARNING: The non-const method changes the matrix!
765  template <typename S>
766  int crack(UT_Vector3T<S> &rvec, const UT_XformOrder &order,
767  int remove_scales=1);
768  template <typename S>
769  int crack(UT_Vector3T<S> &rvec, const UT_XformOrder &order,
770  int remove_scales=1) const;
771  int crack2D(T &r) const;
772 
773  /// Perform the polar decomposition M into an orthogonal matrix Q and an
774  /// symmetric positive-semidefinite matrix S. This is more useful than
775  /// crack() or conditionRotate() when the desire is to blend transforms.
776  /// By default, it gives M=SQ, a left polar decomposition. If reverse is
777  /// false, then it gives M=QS, a right polar decomposition.
778  /// @pre *this is non-singular
779  /// @post *this = Q, and if stretch != 0: *stretch = S
780  /// @return True if successful
781  bool polarDecompose(
782  UT_Matrix3T<T> *stretch = nullptr,
783  bool reverse = true,
784  const int max_iter = 64,
785  const T rel_tol = FLT_EPSILON);
786 
787  /// Turn this matrix into the "closest" rotation matrix.
788  ///
789  /// It uses polarDecompose and then negates the matrix and stretch
790  /// if there is a negative determinant (scale). It returns false iff
791  /// polarDecompose failed, possibly due to a singular matrix.
792  ///
793  /// This is currently the one true way to turn an arbitrary
794  /// matrix into a rotation matrix. If that ever changes,
795  /// put a warning here, and you may want to update
796  /// UT_Matrix4::makeRigidMatrix too.
797  bool makeRotationMatrix(
798  UT_Matrix3T<T> *stretch = nullptr,
799  bool reverse = true,
800  const int max_iter = 64,
801  const T rel_tol = FLT_EPSILON);
802 
803  /// This method will condition the matrix so that it's a valid rotation
804  /// matrix (i.e. crackable). Ideally, the scales should be removed first,
805  /// but this method will attempt to do this as well. It will return the
806  /// conditioned scales if a vector is passed in.
807  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
808  /// @{
809  template <typename S>
810  void conditionRotateT(UT_Vector3T<S> *scales);
811  void conditionRotate(UT_Vector3F *scales=0)
812  { conditionRotateT(scales); }
814  { conditionRotateT(scales); }
815  /// @}
816 
817  /// Extract scales and shears from the matrix leaving the matrix as a nice
818  /// orthogonal rotation matrix. The shears are:
819  /// XY, XZ, and YZ
820  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
821  /// @{
822  template <typename S>
823  void extractScalesT(UT_Vector3T<S> &scales, UT_Vector3T<S> *shears);
824  void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
825  { extractScalesT(scales, shears); }
826  void extractScales(UT_Vector3F &scales, UT_Vector3F *shears=0)
827  { extractScalesT(scales, shears); }
829  UT_Vector3T<fpreal16> *shears=0)
830  { extractScalesT(scales, shears); }
831  /// @}
832 
833  // Extract scales and shears from the matrix leaving the matrix as a nice
834  // orthogonal rotation matrix (assuming it was only a 2D xform to begin
835  // with). The shears are:
836  // XY
837  template <typename S>
838  void extractScales2D(UT_Vector2T<S> &scales, T *shears=0);
839 
840  // Shear the matrix according to the values. This is equivalent to
841  // multiplying the matrix by the shear matrix with the given value.
842  void shearXY(T val);
843  void shearXZ(T val);
844  void shearYZ(T val);
845 
846  /// Post-multiply this matrix by the shear matrix formed by (sxy, sxz, syz)
847  /// @{
848  void shear(T s_xy, T s_xz, T s_yz)
849  {
850  matx[0][0] += matx[0][1]*s_xy + matx[0][2]*s_xz;
851  matx[0][1] += matx[0][2]*s_yz;
852 
853  matx[1][0] += matx[1][1]*s_xy + matx[1][2]*s_xz;
854  matx[1][1] += matx[1][2]*s_yz;
855 
856  matx[2][0] += matx[2][1]*s_xy + matx[2][2]*s_xz;
857  matx[2][1] += matx[2][2]*s_yz;
858  }
859  inline void shear(const UT_Vector3T<T> &sh)
860  { shear(sh(0), sh(1), sh(2)); }
861  /// @}
862 
863  // Solve a 3x3 system of equations whose parameters are held in this
864  // matrix, and whose rhs constants are cx, cy, and cz. The method returns
865  // 0 if the determinant is not 0, and 1 otherwise.
866  template <typename S>
867  int solve(T cx, T cy, T cz,
868  UT_Vector3T<S> &result) const;
869 
870  // Space change operation: right multiply this matrix by the 3x3 matrix
871  // of the transformation which moves the vector space defined by
872  // (iSrc, jSrc, cross(iSrc,jSrc)) into the space defined by
873  // (iDest, jDest, cross(iDest,jDest)). iSrc, jSrc, iDest, and jDest will
874  // be normalized before the operation if norm is 1. This matrix transforms
875  // iSrc into iDest, and jSrc into jDest.
876  template <typename S>
877  void changeSpace(UT_Vector3T<S> &iSrc, UT_Vector3T<S> &jSrc,
878  UT_Vector3T<S> &iDest,UT_Vector3T<S> &jDest,
879  int norm=1);
880  template <typename S>
881  SYS_DEPRECATED(12.0) UT_Matrix3T<T> changeSpace(UT_Vector3T<S> &iSrc, UT_Vector3T<S> &jSrc,
882  UT_Vector3T<S> &iDest,UT_Vector3T<S> &jDest,
883  int norm=1) const;
884 
885  // Multiply this matrix by the general transform matrix built from
886  // translations (tx,ty), degree rotation (rz), scales (sx,sy),
887  // and possibly a pivot point (px,py). The second methos leaves us
888  // unchanged, and returns a new (this*xform) instead. The order of the
889  // multiplies (SRT, RST, Rz, etc) is stored in 'order'. Normally you
890  // will ignore the 'reverse' parameter, which tells us to build the
891  // matrix from last to first xform, and to apply some inverses to
892  // txy, rz, and sxy.
893  void xform(const UT_XformOrder &order,
894  T tx=0.0f, T ty=0.0f, T rz=0.0f,
895  T sx=1.0f, T sy=1.0f,T px=0.0f,T py=0.0f,
896  int reverse=0);
897  SYS_DEPRECATED(12.0) UT_Matrix3T<T> xform(const UT_XformOrder &order,
898  T tx=0.0f, T ty=0.0f, T rz=0.0f,
899  T sx=1.0f, T sy=1.0f,T px=0.0f,T py=0.0f,
900  int reverse=0) const;
901 
902  // this version handles shears as well
903  void xform(const UT_XformOrder &order,
904  T tx, T ty, T rz,
905  T sx, T sy, T s_xy,
906  T px, T py,
907  int reverse=0);
908 
909  // Right multiply this matrix by a 3x3 matrix which scales by a given
910  // amount along the direction of vector v. When applied to a vector w,
911  // the stretched matrix (*this) stretches w in v by the amount given.
912  // If norm is non-zero, v will be normalized prior to the operation.
913  template <typename S>
914  void stretch(UT_Vector3T<S> &v, T amount, int norm=1);
915  template <typename S>
916  SYS_DEPRECATED(12.0) UT_Matrix3T<T> stretch(UT_Vector3T<S> &v, T amount, int norm=1) const;
917 
918  //
919  // This does a test to see if a vector transformed by the matrix
920  // will maintain it's length (i.e. there are no scales in the matrix)
921  int isNormalized() const;
922 
923  // Return the dot product between two rows i and j:
924  T dot(unsigned i, unsigned j) const
925  {
926  return (i <= 2 && j <= 2) ?
927  matx[i][0]*matx[j][0] + matx[i][1]*matx[j][1] +
928  matx[i][2]*matx[j][2] : (T)0;
929  }
930 
931  /// Set the matrix to identity
932  void identity() { *this = 1; }
933  /// Set the matrix to zero
934  void zero() { *this = 0; }
935 
936  int isIdentity() const
937  {
938  // NB: DO NOT USE TOLERANCES
939  return(
940  matx[0][0]==1.0f && matx[0][1]==0.0f &&
941  matx[0][2]==0.0f && matx[1][0]==0.0f &&
942  matx[1][1]==1.0f && matx[1][2]==0.0f &&
943  matx[2][0]==0.0f && matx[2][1]==0.0f &&
944  matx[2][2]==1.0f
945  );
946  }
947 
948  int isZero() const
949  {
950  // NB: DO NOT USE TOLERANCES
951  return (
952  matx[0][0]==0.0f && matx[0][1]==0.0f &&
953  matx[0][2]==0.0f && matx[1][0]==0.0f &&
954  matx[1][1]==0.0f && matx[1][2]==0.0f &&
955  matx[2][0]==0.0f && matx[2][1]==0.0f &&
956  matx[2][2]==0.0f
957  );
958  }
959 
960  /// Return the raw matrix data.
961  // @{
962  const T *data(void) const { return myFloats; }
963  T *data(void) { return myFloats; }
964  // @}
965 
966  /// Compute a hash
967  unsigned hash() const { return SYSvector_hash(data(), tuple_size); }
968 
969  /// Return a matrix entry. No bounds checking on subscripts.
970  // @{
971  SYS_FORCE_INLINE T &operator()(unsigned row, unsigned col) noexcept
972  {
973  UT_ASSERT_P(row < 3 && col < 3);
974  return matx[row][col];
975  }
977  T operator()(unsigned row, unsigned col) const noexcept
978  {
979  UT_ASSERT_P(row < 3 && col < 3);
980  return matx[row][col];
981  }
982  // @}
983 
984  /// Return a matrix row. No bounds checking on subscript.
985  // @{
986  T *operator()(unsigned row)
987  {
988  UT_ASSERT_P(row < 3);
989  return matx[row];
990  }
991  const T *operator()(unsigned row) const
992  {
993  UT_ASSERT_P(row < 3);
994  return matx[row];
995  }
996  inline const UT_Vector3T<T> &operator[](unsigned row) const;
997  inline UT_Vector3T<T> &operator[](unsigned row);
998  // @}
999 
1000  /// Euclidean or Frobenius norm of a matrix.
1001  /// Does sqrt(sum(a_ij ^2))
1003  { return SYSsqrt(getEuclideanNorm2()); }
1004  /// Euclidean norm squared.
1005  T getEuclideanNorm2() const;
1006 
1007  /// Get the squared Euclidean distance between '*this' and 'from'
1008  /// Returns sum_ij(sqr(b_ij-a_ij))
1009  T distanceSquared(const UT_Matrix3T<T> &src);
1010 
1011  /// Get the 1-norm of this matrix, assuming a row vector convention.
1012  /// Returns the maximum absolute row sum. ie. max_i(sum_j(abs(a_ij)))
1013  T getNorm1() const;
1014 
1015  /// Get the inf-norm of this matrix, assuming a row vector convention.
1016  /// Returns the maximum absolute column sum. ie. max_j(sum_i(abs(a_ij)))
1017  T getNormInf() const;
1018 
1019  // I/O methods. Return 0 if read/write successful, -1 if unsuccessful.
1020  int save(std::ostream &os, int binary) const;
1021  bool load(UT_IStream &is);
1022 
1023  void outAsciiNoName(std::ostream &os) const;
1024 
1025  static const UT_Matrix3T<T> &getIdentityMatrix();
1026 
1027  // I/O friends:
1028  friend std::ostream &operator<<(std::ostream &os, const UT_Matrix3T<T> &v)
1029  {
1030  v.writeClassName(os);
1031  v.outAsciiNoName(os);
1032  return os;
1033  }
1034 
1035  /// @{
1036  /// Methods to serialize to a JSON stream. The matrix is stored as an
1037  /// array of 9 reals.
1038  bool save(UT_JSONWriter &w) const;
1039  bool save(UT_JSONValue &v) const;
1040  bool load(UT_JSONParser &p);
1041  /// @}
1042 
1043  /// Returns the vector size
1044  static int entries() { return tuple_size; }
1045 
1046 private:
1047  // Check this matrix to see if it is a valid rotation matrix, and permute
1048  // its elements depending on the rotOrder value in crack(). checkRot()
1049  // returns 0 if OK and 1 otherwise.
1050  int checkRot() const;
1051  void permute(int l0, int l1, int l2);
1052 
1053  // Operation to aid in cofactor computation
1054  inline void coVals(int k, int r[2]) const
1055  {
1056  switch(k)
1057  {
1058  case 0: r[0] = 1; r[1] = 2; break;
1059  case 1: r[0] = 0; r[1] = 2; break;
1060  case 2: r[0] = 0; r[1] = 1; break;
1061  }
1062  }
1063 
1064 
1065  void writeClassName(std::ostream &os) const;
1066  static const char *className();
1067 
1068  // The matrix data:
1069  union {
1070  T matx[3][3];
1071  T myFloats[tuple_size];
1072  };
1073 };
1074 
1075 #include "UT_Vector3.h"
1076 
1077 template <typename T>
1078 template <typename S>
1079 inline
1081 {
1082  matx[0][0] = matx[0][1] = matx[0][2] = vec.x();
1083  matx[1][0] = matx[1][1] = matx[1][2] = vec.y();
1084  matx[2][0] = matx[2][1] = matx[2][2] = vec.z();
1085  return *this;
1086 }
1087 
1088 template <typename T>
1089 template <typename S>
1090 inline
1092 {
1093  T x = vec.x(); T y = vec.y(); T z = vec.z();
1094  matx[0][0]+=x; matx[0][1]+=x; matx[0][2]+=x;
1095  matx[1][0]+=y; matx[1][1]+=y; matx[1][2]+=y;
1096  matx[2][0]+=z; matx[2][1]+=z; matx[2][2]+=z;
1097  return *this;
1098 }
1099 
1100 template <typename T>
1101 template <typename S>
1102 inline
1104 {
1105  T x = vec.x(); T y = vec.y(); T z = vec.z();
1106  matx[0][0]-=x; matx[0][1]-=x; matx[0][2]-=x;
1107  matx[1][0]-=y; matx[1][1]-=y; matx[1][2]-=y;
1108  matx[2][0]-=z; matx[2][1]-=z; matx[2][2]-=z;
1109  return *this;
1110 }
1111 
1112 // Scaled outer product update (given scalar b, row vectors v1 and v2)
1113 // this += b * transpose(v1) * v2
1114 template <typename T>
1115 template <typename S>
1116 inline
1118  const UT_Vector3T<S> &v1,
1119  const UT_Vector3T<S> &v2)
1120 {
1121  T bv1;
1122  bv1 = b * v1.x();
1123  matx[0][0]+=bv1*v2.x();
1124  matx[0][1]+=bv1*v2.y();
1125  matx[0][2]+=bv1*v2.z();
1126  bv1 = b * v1.y();
1127  matx[1][0]+=bv1*v2.x();
1128  matx[1][1]+=bv1*v2.y();
1129  matx[1][2]+=bv1*v2.z();
1130  bv1 = b * v1.z();
1131  matx[2][0]+=bv1*v2.x();
1132  matx[2][1]+=bv1*v2.y();
1133  matx[2][2]+=bv1*v2.z();
1134 }
1135 
1136 template <typename T>
1137 inline
1139 {
1140  UT_ASSERT_P(row < 3);
1141  return *(const UT_Vector3T<T>*)(matx[row]);
1142 }
1143 
1144 template <typename T>
1145 inline
1147 {
1148  UT_ASSERT_P(row < 3);
1149  return *(UT_Vector3T<T>*)(matx[row]);
1150 }
1151 
1152 
1153 // Free floating functions:
1154 template <typename T, typename S>
1155 inline
1157 {
1158  return mat+vec;
1159 }
1160 
1161 template <typename T, typename S>
1162 inline
1164 {
1165  return m1*sc;
1166 }
1167 
1168 template <typename T, typename S>
1169 inline
1171 {
1172  return (m1 * (1.0f/scalar));
1173 }
1174 
1175 template <typename T>
1176 inline
1178 {
1179  return UT_Matrix3T<T>(
1180  SYSmin(v1(0,0), v2(0,0)),
1181  SYSmin(v1(0,1), v2(0,1)),
1182  SYSmin(v1(0,2), v2(0,2)),
1183  SYSmin(v1(1,0), v2(1,0)),
1184  SYSmin(v1(1,1), v2(1,1)),
1185  SYSmin(v1(1,2), v2(1,2)),
1186  SYSmin(v1(2,0), v2(2,0)),
1187  SYSmin(v1(2,1), v2(2,1)),
1188  SYSmin(v1(2,2), v2(2,2))
1189  );
1190 }
1191 
1192 template <typename T>
1193 inline
1195 {
1196  return UT_Matrix3T<T>(
1197  SYSmax(v1(0,0), v2(0,0)),
1198  SYSmax(v1(0,1), v2(0,1)),
1199  SYSmax(v1(0,2), v2(0,2)),
1200  SYSmax(v1(1,0), v2(1,0)),
1201  SYSmax(v1(1,1), v2(1,1)),
1202  SYSmax(v1(1,2), v2(1,2)),
1203  SYSmax(v1(2,0), v2(2,0)),
1204  SYSmax(v1(2,1), v2(2,1)),
1205  SYSmax(v1(2,2), v2(2,2))
1206  );
1207 }
1208 
1209 template <typename T,typename S>
1210 inline
1212 {
1213  return UT_Matrix3T<T>(
1214  SYSlerp(v1(0,0), v2(0,0), t),
1215  SYSlerp(v1(0,1), v2(0,1), t),
1216  SYSlerp(v1(0,2), v2(0,2), t),
1217  SYSlerp(v1(1,0), v2(1,0), t),
1218  SYSlerp(v1(1,1), v2(1,1), t),
1219  SYSlerp(v1(1,2), v2(1,2), t),
1220  SYSlerp(v1(2,0), v2(2,0), t),
1221  SYSlerp(v1(2,1), v2(2,1), t),
1222  SYSlerp(v1(2,2), v2(2,2), t)
1223  );
1224 }
1225 
1226 template<typename T>
1228 {
1230  typedef T DataType;
1231  static const exint TupleSize = 9;
1232  static const bool isVectorType = true;
1233 };
1234 
1235 // Overload for custom formatting of UT_Matrix3T<T> with UTformat.
1236 template<typename T>
1237 UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix3T<T> &v);
1238 
1239 #endif
static int entries()
Returns the vector size.
Definition: UT_Matrix3.h:1044
SYS_FORCE_INLINE T & operator()(unsigned row, unsigned col) noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:971
int isZero() const
Definition: UT_Matrix3.h:948
UT_Matrix3T< T > & operator=(const UT_SymMatrix3T< S > &m)
Convert from a symmetric matrix to non-symmetric.
Definition: UT_Matrix3.h:188
Mat3< typename promote< S, T >::type > operator*(S scalar, const Mat3< T > &m)
Returns M, where for .
Definition: Mat3.h:615
void leftMult(const UT_SymMatrix3T< S > &m)
Multiply given symmetric matrix on the left.
Definition: UT_Matrix3.h:308
#define SYS_STATIC_ASSERT(expr)
UT_Matrix3T< T > transposedCopy() const
Definition: UT_Matrix3.h:614
UT_SymMatrix3T< T > averagedSymMatrix3() const
Convert this to a symmetric matrix, using averaged components.
Definition: UT_Matrix3.h:215
#define SYS_DEPRECATED(__V__)
UT_SymMatrix3T< T > upperTriangularSymMatrix3() const
Convert this to a symmetric matrix, using the upper-triangular portion.
Definition: UT_Matrix3.h:207
UT_Matrix3T< T > & operator*=(T scalar)
Definition: UT_Matrix3.h:376
void leftMult(const UT_Matrix3T< S > &m)
Multiply given matrix3 on the left.
Definition: UT_Matrix3.h:333
constexpr bool operator!=(const UT_Matrix3T< T > &m) const noexcept
Definition: UT_Matrix3.h:363
void orientInverse(const UT_Vector3F &v, T pscale, const UT_Vector3F *s3, const UT_Vector3F *up, const UT_QuaternionF *q)
Definition: UT_Matrix3.h:506
const T * operator()(unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix3.h:991
void UTswap(T &a, T &b)
Definition: UT_Swap.h:35
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
GLboolean invert
Definition: glcorearb.h:548
constexpr bool operator==(const UT_Matrix3T< T > &m) const noexcept
Definition: UT_Matrix3.h:356
const GLdouble * v
Definition: glcorearb.h:836
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Returns M, where for .
Definition: Mat3.h:631
UT_Matrix3T(const UT_SymMatrix3T< S > m)
Construct from a symmetric 3x3 matrix.
Definition: UT_Matrix3.h:160
void extractScales(UT_Vector3F &scales, UT_Vector3F *shears=0)
Definition: UT_Matrix3.h:826
SYS_FORCE_INLINE T operator()(unsigned row, unsigned col) const noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:977
T determinant() const
Definition: UT_Matrix3.h:534
const GLuint GLenum const void * binary
Definition: glcorearb.h:1923
UT_Matrix3T< T > & operator+=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:247
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
UT_Matrix3T< T > SYSmax(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2)
Definition: UT_Matrix3.h:1194
const LowerTri & lowerTri() const
Return reference to the lower triangular elements for symbolic access.
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix3T< T > &v)
int isIdentity() const
Definition: UT_Matrix3.h:936
void pretranslate(const UT_Vector2T< T > &delta)
Definition: UT_Matrix3.h:753
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:72
#define UT_API
Definition: UT_API.h:12
Generic symmetric 3x3 matrix.
Definition: UT_SymMatrix3.h:25
GLint y
Definition: glcorearb.h:102
T * operator()(unsigned row)
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix3.h:986
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:32
T coFactor(int k, int l) const
Definition: UT_Matrix3.h:520
void extractScales(UT_Vector3T< fpreal16 > &scales, UT_Vector3T< fpreal16 > *shears=0)
Definition: UT_Matrix3.h:828
static const exint TupleSize
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:817
SYS_FORCE_INLINE T & x(void)
Definition: UT_Vector3.h:581
void orient(const UT_Vector3D &v, T pscale, const UT_Vector3D *s3, const UT_Vector3D *up, const UT_QuaternionD *q)
Definition: UT_Matrix3.h:496
T * data(void)
Return the raw matrix data.
Definition: UT_Matrix3.h:963
UT_Matrix3T< T > SYSmin(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2)
Definition: UT_Matrix3.h:1177
2D Vector class.
Definition: UT_Vector2.h:137
GLuint buffer
Definition: glcorearb.h:659
png_uint_32 i
Definition: png.h:2877
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:101
SYS_FORCE_INLINE T & z(void)
Definition: UT_Vector3.h:585
GLsizei GLboolean transpose
Definition: glcorearb.h:831
UT_Matrix3T< T > SYSbilerp(const UT_Matrix3T< T > &u0v0, const UT_Matrix3T< T > &u1v0, const UT_Matrix3T< T > &u0v1, const UT_Matrix3T< T > &u1v1, S u, S v)
Definition: UT_Matrix3.h:69
GA_API const UT_StringHolder scale
GLfloat f
Definition: glcorearb.h:1925
bool isEqual(const UT_Matrix3T< T > &m, T tolerance=T(SYS_FTOLERANCE)) const
Definition: UT_Matrix3.h:624
void identity()
Set the matrix to identity.
Definition: UT_Matrix3.h:932
UT_Matrix3T< T > SYSlerp(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2, S t)
Definition: UT_Matrix3.h:1211
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Returns M, where for .
Definition: Mat3.h:641
State solve(const PositiveDefMatrix &A, const Vector< typename PositiveDefMatrix::ValueType > &b, Vector< typename PositiveDefMatrix::ValueType > &x, Preconditioner< typename PositiveDefMatrix::ValueType > &preconditioner, const State &termination=terminationDefaults< typename PositiveDefMatrix::ValueType >())
Solve Ax = b via the preconditioned conjugate gradient method.
int64 exint
Definition: SYS_Types.h:115
double fpreal64
Definition: SYS_Types.h:191
class UT_API UT_Matrix3T
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
Definition: CE_Vector.h:218
static const bool isVectorType
void outerproductUpdateT(T b, const UT_Vector3T< S > &v1, const UT_Vector3T< S > &v2)
Definition: UT_Matrix3.h:1117
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
T matx[3][3]
Definition: UT_Matrix3.h:1070
UT_Matrix3T< T > & operator=(const UT_Matrix3T< S > &m) noexcept
Definition: UT_Matrix3.h:178
constexpr UT_Matrix3T(fpreal64 val) noexcept
Construct identity matrix, multipled by scalar.
Definition: UT_Matrix3.h:99
GLboolean * data
Definition: glcorearb.h:130
png_bytepp row
Definition: png.h:1836
bool INST SYS_FORCE_INLINE UT_Matrix3T(const UT_FixedVector< S, 3, INST > &r0, const UT_FixedVector< S, 3, INST > &r1, const UT_FixedVector< S, 3, INST > &r2) noexcept
Definition: UT_Matrix3.h:126
const Vec2< S > & operator*=(Vec2< S > &v, const Matrix33< T > &m)
Definition: ImathMatrix.h:3330
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
void orientInverse(const UT_Vector3D &v, T pscale, const UT_Vector3D *s3, const UT_Vector3D *up, const UT_QuaternionD *q)
Definition: UT_Matrix3.h:511
void translate(T dx, T dy)
Definition: UT_Matrix3.h:731
GA_API const UT_StringHolder orient
void outerproductUpdate(T b, const UT_Vector3D &v1, const UT_Vector3D &v2)
Definition: UT_Matrix3.h:407
UT_SymMatrix3T< T > lowerTriangularSymMatrix3() const
Convert this to a symmetric matrix, using the lower-triangular portion.
Definition: UT_Matrix3.h:199
UT_Matrix3T< T > & operator=(const UT_Matrix3T< T > &m)=default
Default copy assignment operator.
UT_Matrix3T< T > & operator*=(const UT_SymMatrix3T< S > &m)
Multiply given symmetric matrix on the right.
Definition: UT_Matrix3.h:281
UT_Matrix3T< T > operator-() const
Definition: UT_Matrix3.h:225
const UT_Vector3T< T > & operator[](unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix3.h:1138
void shear(const UT_Vector3T< T > &sh)
Definition: UT_Matrix3.h:859
void shear(T s_xy, T s_xz, T s_yz)
Definition: UT_Matrix3.h:848
Inner class to access the elements symbolically.
IFDmantra py
Definition: HDK_Image.dox:266
void addScaledMat(T k, const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:233
SYS_FORCE_INLINE T & y(void)
Definition: UT_Vector3.h:583
Quaternion class.
Definition: UT_Quaternion.h:44
const T * data(void) const
Return the raw matrix data.
Definition: UT_Matrix3.h:962
void prescale(const UT_Vector3T< T > &s)
Definition: UT_Matrix3.h:716
GA_API const UT_StringHolder up
void outerproductUpdate(T b, const UT_Vector3F &v1, const UT_Vector3F &v2)
Definition: UT_Matrix3.h:403
void translate(const UT_Vector2T< T > &delta)
Definition: UT_Matrix3.h:740
bool isSymmetric(const MatType &m)
Determine if a matrix is symmetric.
Definition: Mat.h:875
png_infop png_bytep png_size_t buffer_size
Definition: png.h:2124
void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
Definition: UT_Matrix3.h:824
GLint GLenum GLint x
Definition: glcorearb.h:408
GLfloat GLfloat v1
Definition: glcorearb.h:816
GLuint GLfloat * val
Definition: glcorearb.h:1607
GA_API const UT_StringHolder pscale
unsigned hash() const
Compute a hash.
Definition: UT_Matrix3.h:967
UT_Matrix3T< T > & operator/=(T scalar)
Definition: UT_Matrix3.h:383
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:75
UT_Matrix3T< T > & operator-=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:262
T getEuclideanNorm() const
Definition: UT_Matrix3.h:1002
void orient(const UT_Vector3F &v, T pscale, const UT_Vector3F *s3, const UT_Vector3F *up, const UT_QuaternionF *q)
Definition: UT_Matrix3.h:491
#define SYS_FTOLERANCE
Definition: SYS_Types.h:202
void zero()
Set the matrix to zero.
Definition: UT_Matrix3.h:934
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:856
void conditionRotate(UT_Vector3D *scales)
Definition: UT_Matrix3.h:813
GLboolean r
Definition: glcorearb.h:1221
#define const
Definition: zconf.h:214
UT_Matrix3T< T > operator/(const UT_Matrix3T< T > &mat, S sc)
Definition: UT_Matrix3.h:1170
void transpose(void)
Definition: UT_Matrix3.h:607
UT_FixedVector< T, 9 > FixedVectorType
Definition: UT_Matrix3.h:1229
T trace() const
Definition: UT_Matrix3.h:540
bool INST SYS_FORCE_INLINE UT_Matrix3T(const UT_FixedVector< S, tuple_size, INST > &v) noexcept
Definition: UT_Matrix3.h:117
void scale(const UT_Vector3T< T > &s)
Definition: UT_Matrix3.h:703
GLenum src
Definition: glcorearb.h:1792