HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups 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_FixedVectorTraits.h"
17 #include "UT_Swap.h"
18 #include "UT_SymMatrix3.h"
19 #include "UT_Vector3.h"
20 #include "UT_VectorTypes.h"
21 
22 #include <SYS/SYS_Deprecated.h>
23 #include <SYS/SYS_Math.h>
24 #include <iosfwd>
25 
26 class UT_IStream;
27 class UT_JSONParser;
28 class UT_JSONWriter;
29 class UT_JSONValue;
30 
31 // Free floating operators that return a UT_Matrix3T object.
32 template <typename T>
34 template <typename T>
36 template <typename T>
38 template <typename T, typename S>
40 template <typename T, typename S>
41 inline UT_Matrix3T<T> operator+(const UT_Vector3T<S> &v, const UT_Matrix3T<T> &m);
42 template <typename T, typename S>
44 template <typename T, typename S>
46 template <typename T, typename S>
48 template <typename T, typename S>
49 inline UT_Matrix3T<T> operator-(const UT_Matrix3T<T> &mat, S sc);
50 template <typename T, typename S>
52 template <typename T, typename S>
53 inline UT_Matrix3T<T> operator/(const UT_Matrix3T<T> &mat, S sc);
54 template <typename T, typename S>
55 inline UT_Matrix3T<T> operator+(S sc, const UT_Matrix3T<T> &mat);
56 template <typename T, typename S>
58 template <typename T, typename S>
59 inline UT_Matrix3T<T> operator*(S sc, const UT_Matrix3T<T> &mat);
60 template <typename T, typename S>
62 
63 template <typename T>
64 inline UT_Matrix3T<T> SYSmin (const UT_Matrix3T<T> &v1, const UT_Matrix3T<T> &v2);
65 template <typename T>
66 inline UT_Matrix3T<T> SYSmax (const UT_Matrix3T<T> &v1, const UT_Matrix3T<T> &v2);
67 template <typename T,typename S>
68 inline UT_Matrix3T<T> SYSlerp(const UT_Matrix3T<T> &v1, const UT_Matrix3T<T> &v2, S t);
69 
70 /// Bilinear interpolation
71 template <typename T,typename S>
72 inline UT_Matrix3T<T> SYSbilerp(const UT_Matrix3T<T> &u0v0, const UT_Matrix3T<T> &u1v0,
73  const UT_Matrix3T<T> &u0v1, const UT_Matrix3T<T> &u1v1,
74  S u, S v)
75 { return SYSlerp(SYSlerp(u0v0, u0v1, v), SYSlerp(u1v0, u1v1, v), u); }
76 
77 /// Barycentric interpolation
78 template <typename T, typename S>
80  const UT_Matrix3T<T> &v1, const UT_Matrix3T<T> &v2, S u, S v)
81 { return v0 * (1 - u - v) + v1 * u + v2 *v; }
82 
83 
84 /// This class implements a 3x3 float matrix in row-major order.
85 ///
86 /// Most of Houdini operates with row vectors that are left-multiplied with
87 /// matrices. e.g., z = v * M
88 ///
89 /// This convention, combined with row-major order, is directly compatible
90 /// with OpenGL matrix requirements.
91 template <typename T>
93 {
94 public:
95 
96  typedef T value_type;
97  static constexpr int tuple_size = 9;
98 
99  /// Construct uninitialized matrix.
100  SYS_FORCE_INLINE UT_Matrix3T() = default;
101 
102  /// Default copy constructor
103  constexpr UT_Matrix3T(const UT_Matrix3T &) = default;
104 
105  /// Default move constructor
106  constexpr UT_Matrix3T(UT_Matrix3T &&) = default;
107 
108  /// Construct identity matrix, multipled by scalar.
109  explicit constexpr UT_Matrix3T(fpreal64 val) noexcept
110  : matx{{T(val),0,0},{0,T(val),0},{0,0,T(val)}}
111  {
112  SYS_STATIC_ASSERT(sizeof(UT_Matrix3T<T>) == tuple_size * sizeof(T));
113  }
114  /// Construct a deep copy of the input row-major data.
115  /// @{
116  template <typename S>
117  explicit constexpr UT_Matrix3T(const S m[3][3]) noexcept
118  : matx{
119  {T(m[0][0]),T(m[0][1]),T(m[0][2])},
120  {T(m[1][0]),T(m[1][1]),T(m[1][2])},
121  {T(m[2][0]),T(m[2][1]),T(m[2][2])}}
122  {}
123  /// @}
124 
125  /// Construct from 3 row vectors
126  constexpr SYS_FORCE_INLINE UT_Matrix3T(
127  const UT_Vector3T<T> &r0,
128  const UT_Vector3T<T> &r1,
129  const UT_Vector3T<T> &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
234  void addScaledMat(T k, const UT_Matrix3T<T> &m)
235  {
236  matx[0][0]+=k*m.matx[0][0];
237  matx[0][1]+=k*m.matx[0][1];
238  matx[0][2]+=k*m.matx[0][2];
239 
240  matx[1][0]+=k*m.matx[1][0];
241  matx[1][1]+=k*m.matx[1][1];
242  matx[1][2]+=k*m.matx[1][2];
243 
244  matx[2][0]+=k*m.matx[2][0];
245  matx[2][1]+=k*m.matx[2][1];
246  matx[2][2]+=k*m.matx[2][2];
247  }
250  {
251  matx[0][0]+=m.matx[0][0];
252  matx[0][1]+=m.matx[0][1];
253  matx[0][2]+=m.matx[0][2];
254 
255  matx[1][0]+=m.matx[1][0];
256  matx[1][1]+=m.matx[1][1];
257  matx[1][2]+=m.matx[1][2];
258 
259  matx[2][0]+=m.matx[2][0];
260  matx[2][1]+=m.matx[2][1];
261  matx[2][2]+=m.matx[2][2];
262  return *this;
263  }
266  {
267  matx[0][0]-=m.matx[0][0];
268  matx[0][1]-=m.matx[0][1];
269  matx[0][2]-=m.matx[0][2];
270 
271  matx[1][0]-=m.matx[1][0];
272  matx[1][1]-=m.matx[1][1];
273  matx[1][2]-=m.matx[1][2];
274 
275  matx[2][0]-=m.matx[2][0];
276  matx[2][1]-=m.matx[2][1];
277  matx[2][2]-=m.matx[2][2];
278  return *this;
279  }
280 
282  {
283  T a, b, c;
284  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
285  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
286  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
287  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
288 
289  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
290  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
291  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
292  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
293 
294  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
295  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
296  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
297  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
298  return *this;
299  }
300 
301  /// Multiply given symmetric matrix on the right
302  template <typename S>
304  {
305  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
306 
307  const LowerTri& l = m.lowerTri();
308  T a, b, c;
309 
310  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
311  matx[0][0] = a*l.q00 + b*l.q10 + c*l.q20;
312  matx[0][1] = a*l.q10 + b*l.q11 + c*l.q21;
313  matx[0][2] = a*l.q20 + b*l.q21 + c*l.q22;
314 
315  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
316  matx[1][0] = a*l.q00 + b*l.q10 + c*l.q20;
317  matx[1][1] = a*l.q10 + b*l.q11 + c*l.q21;
318  matx[1][2] = a*l.q20 + b*l.q21 + c*l.q22;
319 
320  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
321  matx[2][0] = a*l.q00 + b*l.q10 + c*l.q20;
322  matx[2][1] = a*l.q10 + b*l.q11 + c*l.q21;
323  matx[2][2] = a*l.q20 + b*l.q21 + c*l.q22;
324 
325  return *this;
326  }
327 
328  /// Multiply given symmetric matrix on the left
329  template <typename S>
331  {
332  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
333 
334  const LowerTri& l = m.lowerTri();
335  T a, b, c;
336 
337  a = matx[0][0]; b = matx[1][0]; c = matx[2][0];
338  matx[0][0] = a*l.q00 + b*l.q10 + c*l.q20;
339  matx[1][0] = a*l.q10 + b*l.q11 + c*l.q21;
340  matx[2][0] = a*l.q20 + b*l.q21 + c*l.q22;
341 
342  a = matx[0][1]; b = matx[1][1]; c = matx[2][1];
343  matx[0][1] = a*l.q00 + b*l.q10 + c*l.q20;
344  matx[1][1] = a*l.q10 + b*l.q11 + c*l.q21;
345  matx[2][1] = a*l.q20 + b*l.q21 + c*l.q22;
346 
347  a = matx[0][2]; b = matx[1][2]; c = matx[2][2];
348  matx[0][2] = a*l.q00 + b*l.q10 + c*l.q20;
349  matx[1][2] = a*l.q10 + b*l.q11 + c*l.q21;
350  matx[2][2] = a*l.q20 + b*l.q21 + c*l.q22;
351  }
352 
353  /// Multiply given matrix3 on the left
354  template <typename S>
355  void leftMult(const UT_Matrix3T<S> &m)
356  {
357  T a, b, c;
358 
359  a = matx[0][0]; b = matx[1][0]; c = matx[2][0];
360  matx[0][0] = a*m(0,0) + b*m(0,1) + c*m(0,2);
361  matx[1][0] = a*m(1,0) + b*m(1,1) + c*m(1,2);
362  matx[2][0] = a*m(2,0) + b*m(2,1) + c*m(2,2);
363 
364  a = matx[0][1]; b = matx[1][1]; c = matx[2][1];
365  matx[0][1] = a*m(0,0) + b*m(0,1) + c*m(0,2);
366  matx[1][1] = a*m(1,0) + b*m(1,1) + c*m(1,2);
367  matx[2][1] = a*m(2,0) + b*m(2,1) + c*m(2,2);
368 
369  a = matx[0][2]; b = matx[1][2]; c = matx[2][2];
370  matx[0][2] = a*m(0,0) + b*m(0,1) + c*m(0,2);
371  matx[1][2] = a*m(1,0) + b*m(1,1) + c*m(1,2);
372  matx[2][2] = a*m(2,0) + b*m(2,1) + c*m(2,2);
373  }
374 
375  void multiply3(const UT_Matrix4 &m);
376  void multiply3(const UT_DMatrix4 &m);
377 
378  constexpr bool operator==(const UT_Matrix3T<T> &m) const noexcept
379  {
380  return (&m == this) || (
381  matx[0][0]==m(0,0) && matx[0][1]==m(0,1) && matx[0][2]==m(0,2) &&
382  matx[1][0]==m(1,0) && matx[1][1]==m(1,1) && matx[1][2]==m(1,2) &&
383  matx[2][0]==m(2,0) && matx[2][1]==m(2,1) && matx[2][2]==m(2,2) );
384  }
385  constexpr bool operator!=(const UT_Matrix3T<T> &m) const noexcept
386  {
387  return !(*this == m);
388  }
389 
390  // Scalar operators:
391  UT_Matrix3T<T> &operator= (T val)
392  {
393  matx[0][0] = val; matx[0][1] = 0; matx[0][2] = 0;
394  matx[1][0] = 0; matx[1][1] = val; matx[1][2] = 0;
395  matx[2][0] = 0; matx[2][1] = 0; matx[2][2] = val;
396  return *this;
397  }
400  {
401  matx[0][0]*=scalar; matx[0][1]*=scalar; matx[0][2]*=scalar;
402  matx[1][0]*=scalar; matx[1][1]*=scalar; matx[1][2]*=scalar;
403  matx[2][0]*=scalar; matx[2][1]*=scalar; matx[2][2]*=scalar;
404  return *this;
405  }
408  {
409  return operator*=( T(1)/scalar );
410  }
411 
412  // Vector3 operators:
413  template <typename S>
414  inline UT_Matrix3T<T> &operator= (const UT_Vector3T<S> &vec);
415  template <typename S>
416  inline UT_Matrix3T<T> &operator+=(const UT_Vector3T<S> &vec);
417  template <typename S>
418  inline UT_Matrix3T<T> &operator-=(const UT_Vector3T<S> &vec);
419 
420  /// Scaled outer product update (given scalar b, row vectors v1 and v2)
421  /// this += b * transpose(v1) * v2
422  /// @{
423  template <typename S>
424  inline void outerproductUpdateT(T b,
425  const UT_Vector3T<S> &v1,
426  const UT_Vector3T<S> &v2);
429  const UT_Vector3F &v1,
430  const UT_Vector3F &v2)
431  { outerproductUpdateT(b, v1, v2); }
434  const UT_Vector3D &v1,
435  const UT_Vector3D &v2)
436  { outerproductUpdateT(b, v1, v2); }
437  /// @}
438 
439  /// Create a reflection matrix for the given normal to the mirror plane.
440  /// 'plane_normal' should be normalized.
441  /// @{
442  template <typename S>
443  static UT_Matrix3T<T> reflectMat(const UT_Vector3T<S> &plane_normal)
444  {
445  UT_Matrix3T<T> m(1.0);
446  m.outerproductUpdate(-2, plane_normal, plane_normal);
447  return m;
448  }
449  /// @}
450 
451  // Other matrix operations:
452  // Computes the basis of a 3x3 matrix. This is used by OBB code
453  // to determine what orientation of a bounding box best represents
454  // a cloud of points. To do this, first fill this matrix with
455  // the sum of p*pT for all points in the cloud.
456  // The result is in this matrix itself.
457  void getBasis();
458 
459  // Sets this matrix to the canonical 180 rotation matrix (about the y axis).
460  void arbitrary180rot();
461 
462  // Sets this matrix to an arbitrary rotation matrix that would flip v.
463  // This rotation is used in orient() and dihedral() functions when given two
464  // opposing vectors.
465  template <typename S>
466  void arbitrary180rot(const UT_Vector3T<S>& v);
467 
468  /// Compute the dihedral: return the matrix that computes the rotation
469  /// around the axes normal to both a and b, (their cross product), by the
470  /// angle which is between a and b. The resulting matrix maps a onto b. If
471  /// a and b have the same direction, what comes out is the identity matrix.
472  /// If a and b are opposed, the rotation is arbitrary180rot and the method
473  /// returns a vector c of zeroes (check with !c); if all is OK, c != 0.
474  /// The transformation is a symmetry around vector a, then a symmetry
475  /// around (norm(a) and norm(b)). If a or b needs to be normalized, pass a
476  /// non-zero value in norm.
477  /// The second function places the result in *this, and returns 0 if a and b
478  /// are not opposed; otherwise, it returns 1. It DOES NOT affect
479  /// *this if they are opposed, so return must be checked.
480  // @{
481  template <typename S>
482  static UT_Matrix3T<T> dihedral(UT_Vector3T<S> &a, UT_Vector3T<S> &b,
483  UT_Vector3T<S> &c,int norm=1);
484  /// @note If dihedral() returns 1, this matrix is NOT modified!
485  template <typename S>
486  int dihedral(UT_Vector3T<S> &a, UT_Vector3T<S> &b,
487  int norm=1);
488  // @}
489 
490  // Compute a lookat matrix: These functions will compute a rotation matrix
491  // (yes, with all the properties of a rotation matrix), which will provide
492  // the rotates needed for "from" to look at "to". One method uses a "roll"
493  // the other method uses an "up" vector to determine the orientation. The
494  // "roll" is not as well defined as using an "up" vector. If the two points
495  // are co-incident, the result will be an identity matrix. If norm is set,
496  // then the up vector will be normalized.
497  // The lookat matrix will have the -Z axis pointing at the "to" point.
498  // The y axis will be pointing "up"
499  template <typename S>
500  void lookat(const UT_Vector3T<S> &from, const UT_Vector3T<S> &to,
501  T roll = 0);
502  template <typename S>
503  void lookat(const UT_Vector3T<S> &from, const UT_Vector3T<S> &to,
504  const UT_Vector3T<S> &up);
505 
506 
507  // Compute the transform matrix to orient given a direction and an up vector
508  // If the direction and up are not orthogonal, then the up vector will be
509  // shifted along the direction to make it orthogonal... If the up and
510  // direction vectors are co-linear, then an identity matrix will be
511  // returned.
512  // The second function will return 0 to indicate this. The inputs may
513  // be modified by the orient functions.
514  template <typename S>
515  int orient(UT_Vector3T<S> &dir, UT_Vector3T<S> &up, int norm=1);
516  template <typename S>
517  int orientInverse(UT_Vector3T<S> &dir, UT_Vector3T<S> &up, int norm=1);
518 
519 
520  // Computes a transform to orient to a given direction (v) with a scale
521  // (pscale). The up vector (up) is optional and will orient the matrix to
522  // this up vector. If no up vector is given, the z axis will be oriented to
523  // point in the v direction. If a quaternion (q) is specified, the
524  // orientation will be additionally transformed by the rotation specified
525  // by the quaternion.
526  // The matrix is scaled non-uniformly about each axis using s3, if s3
527  // is non-zero. A uniform scale of pscale is applied regardless, so if
528  // s3 is non-zero, the x axis will be scaled by pscale * s3->x().
529  template <typename S>
530  void orientT(const UT_Vector3T<S>& v,
531  T pscale, const UT_Vector3T<S> *s3,
532  const UT_Vector3T<S>* up,
533  const UT_QuaternionT<S> * q);
534  void orient(const UT_Vector3F &v,
535  T pscale, const UT_Vector3F *s3,
536  const UT_Vector3F *up,
537  const UT_QuaternionF *q)
538  { orientT(v, pscale, s3, up, q); }
539  void orient(const UT_Vector3D &v,
540  T pscale, const UT_Vector3D *s3,
541  const UT_Vector3D *up,
542  const UT_QuaternionD *q)
543  { orientT(v, pscale, s3, up, q); }
544  template <typename S>
545  void orientInverseT(const UT_Vector3T<S>& v,
546  T pscale, const UT_Vector3T<S> *s3,
547  const UT_Vector3T<S>* up,
548  const UT_QuaternionT<S> * q);
550  T pscale, const UT_Vector3F *s3,
551  const UT_Vector3F *up,
552  const UT_QuaternionF *q)
553  { orientInverseT(v, pscale, s3, up, q); }
555  T pscale, const UT_Vector3D *s3,
556  const UT_Vector3D *up,
557  const UT_QuaternionD *q)
558  { orientInverseT(v, pscale, s3, up, q); }
559 
560  // Return the cofactor of the matrix, ie the determinant of the 2x2
561  // submatrix that results from removing row 'k' and column 'l' from the
562  // 3x3.
564  T coFactor(int k, int l) const
565  {
566  int r[2], c[2];
567 
568  // r, c should evaluate to compile time constants
569  coVals(k, r);
570  coVals(l, c);
571  if ((k ^ l) & 1)
572  UTswap(c[0], c[1]);
573 
574  return matx[r[0]][c[0]]*matx[r[1]][c[1]] -
575  matx[r[0]][c[1]]*matx[r[1]][c[0]];
576  }
577 
578  T determinant() const
579  {
580  return(matx[0][0]*coFactor(0,0) +
581  matx[0][1]*coFactor(0,1) +
582  matx[0][2]*coFactor(0,2));
583  }
584  T trace() const
585  { return matx[0][0] + matx[1][1] + matx[2][2]; }
586 
587  /// Computes the eigenvalues. Returns number of real eigenvalues
588  /// found. Uses UT_RootFinder::cubic
589  /// @param r The real eigenvalues
590  /// @param i The imaginary eigenvalues
591  template <typename S>
592  int eigenvalues(UT_Vector3T<S> &r, UT_Vector3T<S> &i) const;
593 
594  /// Invert this matrix and return 0 if OK, 1 if singular.
595  /// If singular, the matrix will be in an undefined state.
596  int invert();
597  /// Invert the matrix and return 0 if OK, 1 if singular.
598  /// Puts the inverted matrix in m, and leaves this matrix unchanged.
599  /// If singular, the inverted matrix will be in an undefined state.
600  int invert(UT_Matrix3T<T> &m)const;
601 
602  /// Use Kramer's method to compute the matrix inverse
603  /// If abs( det(m) ) <= abs_det_threshold, then return 1 without changing m
604  /// Otherwise, return 0, storing the inverse matrix in m
605  ///
606  /// NOTE: The default FLT_EPSILON is kept here to preserve existing behavior
607  /// This is not a good default!
608  /// The right threshold must be decided separately for each use case.
609  int invertKramer(UT_Matrix3T<T> &m, T abs_det_threshold = FLT_EPSILON) const;
610 
611  // Shorthand for invertKramer(*this)
612  int invertKramer(T abs_det_threshold = FLT_EPSILON);
613 
614  // Compute the pseudoinverse of *this.
615  // Though the function is named `Symmetric`, *this can be asymmetric.
616  // *this does NOT have to be non-singular. Singular matrices will be
617  // inverted by filtering out the singular component.
618  // This means you can reliably solve:
619  // M x = b
620  // for the x that is closest to satisfying b
621  // Returns 0 on success, 1 if something really bad happened.
622  int safeInvertSymmetric(T tol=1e-6f);
623 
624  // Diagonalize *this.
625  // *this should be symmetric.
626  // The matrix is factored into:
627  // *this = Rt D R
628  // The diagonalization is done with a serios of jacobi rotations.
629  // *this is unchanged by the operations.
630  // Returns true if successful, false if reached maximum iterations rather
631  // than desired tolerance.
632  // Tolerance is with respect to the maximal element of the matrix.
633  bool diagonalizeSymmetric(UT_Matrix3T<T> &R, UT_Matrix3T<T> &D, T tol=1e-6f, int maxiter = 100) const;
634 
635  // Compute the SVD decomposition of *this
636  // The matrix is factored into
637  // *this = U * S * Vt
638  // Where S is diagonal, and U and Vt are both orthognal matrices
639  // Tolerance is with respect to the maximal element of the matrix
640  void svdDecomposition(UT_Matrix3T<T> &U, UT_Matrix3T<T> &S, UT_Matrix3T<T> &V, T tol=1e-6f) const;
641 
642  /// Splits a covariance matrix into a scale & rotation component.
643  /// This should be built by a series of outer product updates.
644  /// R is the rotation component, S the inverse scale.
645  /// If this is A, finds the inverse square root of AtA, S.
646  /// We then set R = transpose(AS) to give us a rotation matrix.
647  /// NOTE: For general matrices, use makeRotationMatrix()!
648  void splitCovarianceToRotationScale(UT_Matrix3T<T> &R, UT_Matrix3T<T> &S, T tol=1e-6f) const;
649 
650  bool isSymmetric(T tolerance = T(SYS_FTOLERANCE)) const;
651 
652  // Transpose this matrix or return its transpose.
653  void transpose()
654  {
655  T tmp;
656  tmp=matx[0][1]; matx[0][1]=matx[1][0]; matx[1][0]=tmp;
657  tmp=matx[0][2]; matx[0][2]=matx[2][0]; matx[2][0]=tmp;
658  tmp=matx[1][2]; matx[1][2]=matx[2][1]; matx[2][1]=tmp;
659  }
661  {
662  return UT_Matrix3T<T>(matx[0][0], matx[1][0], matx[2][0],
663  matx[0][1], matx[1][1], matx[2][1],
664  matx[0][2], matx[1][2], matx[2][2]);
665  }
666 
667  /// Check for equality within a tolerance level
668  bool isEqual( const UT_Matrix3T<T> &m,
669  T tolerance=T(SYS_FTOLERANCE) ) const
670  {
671  return (&m == this) || (
672  SYSisEqual( matx[0][0], m.matx[0][0], tolerance ) &&
673  SYSisEqual( matx[0][1], m.matx[0][1], tolerance ) &&
674  SYSisEqual( matx[0][2], m.matx[0][2], tolerance ) &&
675 
676  SYSisEqual( matx[1][0], m.matx[1][0], tolerance ) &&
677  SYSisEqual( matx[1][1], m.matx[1][1], tolerance ) &&
678  SYSisEqual( matx[1][2], m.matx[1][2], tolerance ) &&
679 
680  SYSisEqual( matx[2][0], m.matx[2][0], tolerance ) &&
681  SYSisEqual( matx[2][1], m.matx[2][1], tolerance ) &&
682  SYSisEqual( matx[2][2], m.matx[2][2], tolerance ) );
683  }
685  int ulps=50 ) const
686  {
687  return (&m == this) || (
688  SYSalmostEqual( matx[0][0], m.matx[0][0], ulps ) &&
689  SYSalmostEqual( matx[0][1], m.matx[0][1], ulps ) &&
690  SYSalmostEqual( matx[0][2], m.matx[0][2], ulps ) &&
691 
692  SYSalmostEqual( matx[1][0], m.matx[1][0], ulps ) &&
693  SYSalmostEqual( matx[1][1], m.matx[1][1], ulps ) &&
694  SYSalmostEqual( matx[1][2], m.matx[1][2], ulps ) &&
695 
696  SYSalmostEqual( matx[2][0], m.matx[2][0], ulps ) &&
697  SYSalmostEqual( matx[2][1], m.matx[2][1], ulps ) &&
698  SYSalmostEqual( matx[2][2], m.matx[2][2], ulps ) );
699  }
700 
701 
702  /// Check for lower triangular within a tolerance level to 0
703  bool isLowerTriangular(T tolerance=T(SYS_FTOLERANCE)) const
704  {
705  return SYSequalZero(matx[0][1], tolerance) &&
706  SYSequalZero(matx[0][2], tolerance) &&
707  SYSequalZero(matx[1][2], tolerance);
708  }
709 
710  /// Post-multiply this matrix by a 3x3 rotation matrix determined by the
711  /// axis and angle of rotation in radians.
712  /// If 'norm' is not 0, the axis vector is normalized before computing the
713  /// rotation matrix. rotationMat() returns a rotation matrix, and could as
714  /// well be defined as a free floating function.
715  /// @{
716  template <typename S>
717  void rotate(UT_Vector3T<S> &axis, T theta, int norm=1);
718  void rotate(UT_Axis3::axis a, T theta);
719  template<UT_Axis3::axis A>
720  void rotate(T theta);
721  /// @}
722 
723  /// Post-multiply this matrix by a 3x3 rotation matrix (on the right)
724  /// for a quarter turn (90 degrees) around the specified axis
725  template<UT_Axis3::axis A,bool reverse=false>
727  {
728  constexpr uint col0 = (A == UT_Axis3::XAXIS) ? 1 : ((A == UT_Axis3::YAXIS) ? 2 : 0);
729  constexpr uint col1 = (A == UT_Axis3::XAXIS) ? 2 : ((A == UT_Axis3::YAXIS) ? 0 : 1);
730  for (uint row = 0; row < 3; ++row)
731  {
732  T v1 = matx[row][col0];
733  if (!reverse)
734  {
735  matx[row][col0] = -matx[row][col1];
736  matx[row][col1] = v1;
737  }
738  else
739  {
740  matx[row][col0] = matx[row][col1];
741  matx[row][col1] = -v1;
742  }
743  }
744  }
745 
746  /// Post-multiply this matrix by a 3x3 rotation matrix (on the right)
747  /// for a half turn (180 degrees) around the specified axis
748  template<UT_Axis3::axis A>
750  {
751  // In this case, order doesn't matter, so make col0 and col1 in increasing order.
752  constexpr uint col0 = (A == UT_Axis3::XAXIS) ? 1 : 0;
753  constexpr uint col1 = (A == UT_Axis3::ZAXIS) ? 1 : 2;
754  for (uint row = 0; row < 3; ++row)
755  {
756  matx[row][col0] = -matx[row][col0];
757  matx[row][col1] = -matx[row][col1];
758  }
759  }
760 
761  /// This is just a helper function for code handling quarter turns exactly.
762  /// NOTE: theta is in *radians* already, not degrees!
763  template<UT_Axis3::axis A>
765  {
766  if (theta)
767  rotate<A>(theta);
768  else if (qturns)
769  {
770  if (qturns&2)
771  rotateHalf<A>();
772  if (qturns&1)
773  rotateQuarter<A>();
774  }
775  }
776 
777  /// Create a rotation matrix for the given angle in radians around the axis
778  /// @{
779  template <typename S>
780  static UT_Matrix3T<T> rotationMat(UT_Vector3T<S> &axis, T theta, int norm=1);
781  static UT_Matrix3T<T> rotationMat(UT_Axis3::axis a, T theta);
782  /// @}
783 
784  /// Pre-multiply this matrix by the theta radians rotation around the axis
785  /// @{
786  template <typename S>
787  void prerotate(UT_Vector3T<S> &axis, T theta, int norm=1);
788  void prerotate(UT_Axis3::axis a, T theta);
789  template<UT_Axis3::axis A>
790  void prerotate(T theta);
791  /// @}
792 
793  /// Pre-multiply this matrix by a 3x3 rotation matrix (on the left)
794  /// for a quarter turn (90 degrees) around the specified axis
795  template<UT_Axis3::axis A,bool reverse=false>
797  {
798  constexpr uint row0 = (A == UT_Axis3::XAXIS) ? 1 : ((A == UT_Axis3::YAXIS) ? 2 : 0);
799  constexpr uint row1 = (A == UT_Axis3::XAXIS) ? 2 : ((A == UT_Axis3::YAXIS) ? 0 : 1);
800  T v1[4];
801  for (uint col = 0; col < 3; ++col)
802  v1[col] = matx[row0][col];
803  if (!reverse)
804  {
805  for (uint col = 0; col < 3; ++col)
806  matx[row0][col] = matx[row1][col];
807  for (uint col = 0; col < 3; ++col)
808  matx[row1][col] = -v1[col];
809  }
810  else
811  {
812  for (uint col = 0; col < 3; ++col)
813  matx[row0][col] = -matx[row1][col];
814  for (uint col = 0; col < 3; ++col)
815  matx[row1][col] = v1[col];
816  }
817  }
818 
819  /// Pre-multiply this matrix by a 3x3 rotation matrix (on the left)
820  /// for a half turn (180 degrees) around the specified axis
821  template<UT_Axis3::axis A>
823  {
824  // In this case, order doesn't matter, so make row0 and row1 in increasing order.
825  constexpr uint row0 = (A == UT_Axis3::XAXIS) ? 1 : 0;
826  constexpr uint row1 = (A == UT_Axis3::ZAXIS) ? 1 : 2;
827  for (uint col = 0; col < 3; ++col)
828  matx[row0][col] = -matx[row0][col];
829  for (uint col = 0; col < 3; ++col)
830  matx[row1][col] = -matx[row1][col];
831  }
832 
833  /// Pre-rotate by rx, ry, rz radians around the three basic axes in the
834  /// order given by UT_XformOrder.
835  /// @{
836  void prerotate(T rx, T ry, T rz,
837  const UT_XformOrder &order);
838  inline void prerotate(const UT_Vector3T<T> &rad, const UT_XformOrder &order)
839  { prerotate(rad(0), rad(1), rad(2), order); }
840  /// @}
841 
842 
843  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
844  /// order given by UT_XformOrder.
845  /// @{
846  void rotate(T rx, T ry, T rz,
847  const UT_XformOrder &ord);
848  inline void rotate(const UT_Vector3T<T> &rad, const UT_XformOrder &ord)
849  { rotate(rad(0), rad(1), rad(2), ord); }
850  /// @}
851 
852  /// Post-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
853  /// @{
854  void scale(T sx, T sy, T sz)
855  {
856  matx[0][0] *= sx; matx[0][1] *= sy; matx[0][2] *= sz;
857  matx[1][0] *= sx; matx[1][1] *= sy; matx[1][2] *= sz;
858  matx[2][0] *= sx; matx[2][1] *= sy; matx[2][2] *= sz;
859  }
861  void scale(const UT_Vector3T<T> &s)
862  { scale(s(0), s(1), s(2)); }
863  /// @}
864 
865  /// Pre-multiply this matrix by a scale matrix with diagonal (sx, sy, sz)
866  /// @{
867  void prescale(T sx, T sy, T sz)
868  {
869  matx[0][0] *= sx; matx[1][0] *= sy; matx[2][0] *= sz;
870  matx[0][1] *= sx; matx[1][1] *= sy; matx[2][1] *= sz;
871  matx[0][2] *= sx; matx[1][2] *= sy; matx[2][2] *= sz;
872  }
874  void prescale(const UT_Vector3T<T> &s)
875  { prescale(s(0), s(1), s(2)); }
876  /// @}
877 
878  /// Negates this matrix, i.e. multiplies it by -1.
880  {
881  matx[0][0] = -matx[0][0]; matx[0][1] = -matx[0][1]; matx[0][2] = -matx[0][2];
882  matx[1][0] = -matx[1][0]; matx[1][1] = -matx[1][1]; matx[1][2] = -matx[1][2];
883  matx[2][0] = -matx[2][0]; matx[2][1] = -matx[2][1]; matx[2][2] = -matx[2][2];
884  }
885 
886  /// Post-multiply this matrix by a translation matrix determined by (dx,dy)
887  /// @{
888  void translate(T dx, T dy)
889  {
890  matx[0][0] += matx[0][2] * dx;
891  matx[0][1] += matx[0][2] * dy;
892  matx[1][0] += matx[1][2] * dx;
893  matx[1][1] += matx[1][2] * dy;
894  matx[2][0] += matx[2][2] * dx;
895  matx[2][1] += matx[2][2] * dy;
896  }
898  void translate(const UT_Vector2T<T> &delta)
899  { translate(delta(0), delta(1)); }
900  /// @}
901 
902  /// Pre-multiply this matrix by the translation matrix determined by (dx,dy)
903  /// @{
904  void pretranslate(T dx, T dy)
905  {
906  matx[2][0] += matx[0][0] * dx + matx[1][0] * dy;
907  matx[2][1] += matx[0][1] * dx + matx[1][1] * dy;
908  matx[2][2] += matx[0][2] * dx + matx[1][2] * dy;
909  }
911  void pretranslate(const UT_Vector2T<T> &delta)
912  { pretranslate(delta(0), delta(1)); }
913  /// @}
914 
915  /// Generate the x, y, and z values of rotation in radians.
916  /// Return 0 if successful, and a non-zero value otherwise: 1 if the matrix
917  /// is not a valid rotation matrix, 2 if rotOrder is invalid, and 3 for
918  /// other errors. rotOrder must be given as a UT_XformOrder permulation.
919  /// WARNING: For animation or transform blending, use polarDecompose()
920  /// or makeRotationMatrix()!
921  /// @{
922  template <typename S>
923  int crack(UT_Vector3T<S> &rvec, const UT_XformOrder &order) const;
924  template <typename S>
925  int crack2D(S &r) const;
926  /// @}
927 
928  /// Extract the rotation (in radians), and stretch
929  /// components of the 3x3 matrix, preferably using polar decomposition.
930  /// This method is slower than alternatives (explode, crack), but provides
931  /// better results for animation.
932  /// @returns true if the polar decomposition succeeded, false otherwise
933  /// Regardless of the return value, sensible values for translation
934  /// rotation and stretch are computed.
935  template <typename S>
936  bool decompose(const UT_XformOrder &order,
938  UT_Matrix3T<T> &stretch,
939  const int max_iter = 64,
940  const T rel_tol = FLT_EPSILON) const;
941 
942  /// Composes a 3x3 transform matrix given the rotation (in
943  /// radians), and stretch matrix components. This is the inverse of the
944  /// decompose method.
945  template <typename S>
946  void compose(const UT_XformOrder &order,
947  const UT_Vector3T<S> &rot,
948  const UT_Matrix3T<T> &stretch);
949 
950 
951  /// Perform the polar decomposition M into an orthogonal matrix Q and an
952  /// symmetric positive-semidefinite matrix S. This is more useful than
953  /// crack() or conditionRotate() when the desire is to blend transforms.
954  /// By default, it gives M=SQ, a left polar decomposition. If reverse is
955  /// false, then it gives M=QS, a right polar decomposition.
956  /// @pre *this is non-singular
957  /// @post *this = Q, and if stretch != 0: *stretch = S
958  /// @return True if successful
959  bool polarDecompose(
960  UT_Matrix3T<T> *stretch = nullptr,
961  bool reverse = true,
962  const int max_iter = 64,
963  const T rel_tol = FLT_EPSILON);
964 
965  /// Turn this matrix into the "closest" rotation matrix.
966  ///
967  /// It uses polarDecompose and then negates the matrix and stretch
968  /// if there is a negative determinant (scale). It returns false iff
969  /// polarDecompose failed, possibly due to a singular matrix.
970  ///
971  /// This is currently the one true way to turn an arbitrary
972  /// matrix into a rotation matrix. If that ever changes,
973  /// put a warning here, and you may want to update
974  /// UT_Matrix4::makeRigidMatrix too.
975  bool makeRotationMatrix(
976  UT_Matrix3T<T> *stretch = nullptr,
977  bool reverse = true,
978  const int max_iter = 64,
979  const T rel_tol = FLT_EPSILON);
980 
981  /// This method will condition the matrix so that it's a valid rotation
982  /// matrix (i.e. crackable). Ideally, the scales should be removed first,
983  /// but this method will attempt to do this as well. It will return the
984  /// conditioned scales if a vector is passed in.
985  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
986  /// @{
987  template <typename S>
988  void conditionRotateT(UT_Vector3T<S> *scales);
989  void conditionRotate(UT_Vector3F *scales=0)
990  { conditionRotateT(scales); }
992  { conditionRotateT(scales); }
993  /// @}
994 
995  /// Extract scales and shears leaving this as an orthogonal rotation matrix
996  /// using the transform order Scales * Shears * Rotate.
997  /// @note The shears are in the order [XY, XZ, YZ]
998  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
999  /// @{
1000  template <typename S>
1001  void extractScalesT(UT_Vector3T<S> &scales, UT_Vector3T<S> *shears);
1002  void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
1003  { extractScalesT(scales, shears); }
1004  void extractScales(UT_Vector3F &scales, UT_Vector3F *shears=0)
1005  { extractScalesT(scales, shears); }
1007  UT_Vector3T<fpreal16> *shears=0)
1008  { extractScalesT(scales, shears); }
1009  /// @}
1010 
1011  /// Extract scales and shears leaving this as an orthogonal rotation matrix
1012  /// (assuming it was only a 2D xform to begin with) using the transform
1013  /// order Rotate * Scales * Shears. The shears are XY.
1014  template <typename S>
1015  void extractScales2D(UT_Vector2T<S> &scales, S *shears=0);
1016 
1017  /// Extract scales and shears leaving this as an orthogonal rotation matrix
1018  /// using the transform order Rotate * Scales * Shears.
1019  /// @note The shears are in the order [XY, XZ, YZ]
1020  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
1021  template <typename S>
1022  void rightExtractScales(UT_Vector3T<S> &scales,
1023  UT_Vector3T<S> *shears = nullptr);
1024 
1025  /// Extract scales and shears leaving this as an orthogonal rotation matrix
1026  /// (assuming it was only a 2D xform to begin with) using the transform
1027  /// order Scales * Shears * Rotate. The shears are XY.
1028  template <typename S>
1029  void rightExtractScales2D(UT_Vector2T<S> &scales,
1030  S *shears = nullptr);
1031 
1032  // Shear the matrix according to the values. This is equivalent to
1033  // multiplying the matrix by the shear matrix with the given value.
1034  void shearXY(T val);
1035  void shearXZ(T val);
1036  void shearYZ(T val);
1037 
1038  /// Post-multiply this matrix by the shear matrix formed by (sxy, sxz, syz)
1039  /// @{
1040  void shear(T s_xy, T s_xz, T s_yz)
1041  {
1042  matx[0][0] += matx[0][1]*s_xy + matx[0][2]*s_xz;
1043  matx[0][1] += matx[0][2]*s_yz;
1044 
1045  matx[1][0] += matx[1][1]*s_xy + matx[1][2]*s_xz;
1046  matx[1][1] += matx[1][2]*s_yz;
1047 
1048  matx[2][0] += matx[2][1]*s_xy + matx[2][2]*s_xz;
1049  matx[2][1] += matx[2][2]*s_yz;
1050  }
1052  void shear(const UT_Vector3T<T> &sh)
1053  { shear(sh(0), sh(1), sh(2)); }
1054  /// @}
1055 
1056  // Solve a 3x3 system of equations A*x=b, where A is this matrix,
1057  // b or (cx, cy, cz) is given and x is unknown. The method returns 0 if the
1058  // determinant is not 0, and 1 otherwise.
1059  template <typename S>
1060  int solve(T cx, T cy, T cz,
1061  UT_Vector3T<S> &result) const;
1062  template <typename S>
1063  int solve(const UT_Vector3T<S> &b,
1064  UT_Vector3T<S> &result) const;
1065 
1066  // Solve a 3x3 system of equations x*A=b, where A is this matrix,
1067  // b or (cx, cy, cz) is given and x is unknown. The method returns 0 if the
1068  // determinant is not 0, and 1 otherwise.
1069  template <typename S>
1070  int solveTranspose(T cx, T cy, T cz,
1071  UT_Vector3T<S> &result) const;
1072  template <typename S>
1073  int solveTranspose(const UT_Vector3T<S> &b,
1074  UT_Vector3T<S> &result) const;
1075 
1076  // Space change operation: right multiply this matrix by the 3x3 matrix
1077  // of the transformation which moves the vector space defined by
1078  // (iSrc, jSrc, cross(iSrc,jSrc)) into the space defined by
1079  // (iDest, jDest, cross(iDest,jDest)). iSrc, jSrc, iDest, and jDest will
1080  // be normalized before the operation if norm is 1. This matrix transforms
1081  // iSrc into iDest, and jSrc into jDest.
1082  template <typename S>
1083  void changeSpace(UT_Vector3T<S> &iSrc, UT_Vector3T<S> &jSrc,
1084  UT_Vector3T<S> &iDest,UT_Vector3T<S> &jDest,
1085  int norm=1);
1086 
1087  // Multiply this matrix by the general transform matrix built from
1088  // translations (tx,ty), degree rotation (rz), scales (sx,sy),
1089  // and possibly a pivot point (px,py). The second methos leaves us
1090  // unchanged, and returns a new (this*xform) instead. The order of the
1091  // multiplies (SRT, RST, Rz, etc) is stored in 'order'. Normally you
1092  // will ignore the 'reverse' parameter, which tells us to build the
1093  // matrix from last to first xform, and to apply some inverses to
1094  // txy, rz, and sxy.
1095  void xform(const UT_XformOrder &order,
1096  T tx=0, T ty=0, T rz=0,
1097  T sx=1, T sy=1, T px=0,T py=0,
1098  int reverse=0);
1099 
1100  // this version handles shears as well
1101  void xform(const UT_XformOrder &order,
1102  T tx, T ty, T rz,
1103  T sx, T sy, T s_xy,
1104  T px, T py,
1105  int reverse=0);
1106 
1107  // Right multiply this matrix by a 3x3 matrix which scales by a given
1108  // amount along the direction of vector v. When applied to a vector w,
1109  // the stretched matrix (*this) stretches w in v by the amount given.
1110  // If norm is non-zero, v will be normalized prior to the operation.
1111  template <typename S>
1112  void stretch(UT_Vector3T<S> &v, T amount, int norm=1);
1113  template <typename S>
1114  SYS_DEPRECATED(12.0) UT_Matrix3T<T> stretch(UT_Vector3T<S> &v, T amount, int norm=1) const;
1115 
1116  //
1117  // This does a test to see if a vector transformed by the matrix
1118  // will maintain it's length (i.e. there are no scales in the matrix)
1119  int isNormalized() const;
1120 
1121  // Return the dot product between two rows i and j:
1122  T dot(unsigned i, unsigned j) const
1123  {
1124  return rowDot( i, j );
1125  }
1126 
1127  /// Set the matrix to identity
1128  void identity() { *this = 1; }
1129  /// Set the matrix to zero
1130  void zero() { *this = 0; }
1131 
1132  bool isIdentity() const
1133  {
1134  // NB: DO NOT USE TOLERANCES
1135  return(
1136  matx[0][0]==1 && matx[0][1]==0 &&
1137  matx[0][2]==0 && matx[1][0]==0 &&
1138  matx[1][1]==1 && matx[1][2]==0 &&
1139  matx[2][0]==0 && matx[2][1]==0 &&
1140  matx[2][2]==1
1141  );
1142  }
1143 
1144  bool isZero() const
1145  {
1146  // NB: DO NOT USE TOLERANCES
1147  return (
1148  matx[0][0]==0 && matx[0][1]==0 &&
1149  matx[0][2]==0 && matx[1][0]==0 &&
1150  matx[1][1]==0 && matx[1][2]==0 &&
1151  matx[2][0]==0 && matx[2][1]==0 &&
1152  matx[2][2]==0
1153  );
1154  }
1155 
1156  /// Return the raw matrix data.
1157  // @{
1158  const T *data() const { return myFloats; }
1159  T *data() { return myFloats; }
1160  // @}
1161 
1162  /// Compute a hash
1163  unsigned hash() const { return SYSvector_hash(data(), tuple_size); }
1164 
1165  /// Return a matrix entry. No bounds checking on subscripts.
1166  // @{
1167  SYS_FORCE_INLINE T &operator()(unsigned row, unsigned col) noexcept
1168  {
1169  UT_ASSERT_P(row < 3 && col < 3);
1170  return matx[row][col];
1171  }
1173  T operator()(unsigned row, unsigned col) const noexcept
1174  {
1175  UT_ASSERT_P(row < 3 && col < 3);
1176  return matx[row][col];
1177  }
1178  // @}
1179 
1180  /// Return a matrix row. No bounds checking on subscript.
1181  // @{
1182  T *operator()(unsigned row)
1183  {
1184  UT_ASSERT_P(row < 3);
1185  return matx[row];
1186  }
1187  const T *operator()(unsigned row) const
1188  {
1189  UT_ASSERT_P(row < 3);
1190  return matx[row];
1191  }
1192  inline const UT_Vector3T<T> &operator[](unsigned row) const;
1193  inline UT_Vector3T<T> &operator[](unsigned row);
1194  // @}
1195 
1196  /// Dot product with another matrix
1197  /// Does dot(a,b) = sum_ij a_ij * b_ij
1198  T dot(const UT_Matrix3T<T> &m) const;
1199 
1200  /// Euclidean or Frobenius norm of a matrix.
1201  /// Does sqrt(sum(a_ij ^2))
1203  { return SYSsqrt(getEuclideanNorm2()); }
1204  /// Euclidean norm squared.
1205  T getEuclideanNorm2() const;
1206 
1207  /// Get the squared Euclidean distance between '*this' and 'from'
1208  /// Returns sum_ij(sqr(b_ij-a_ij))
1209  T distanceSquared(const UT_Matrix3T<T> &src);
1210 
1211  /// Get the 1-norm of this matrix, assuming a row vector convention.
1212  /// Returns the maximum absolute row sum. ie. max_i(sum_j(abs(a_ij)))
1213  T getNorm1() const;
1214 
1215  /// Get the inf-norm of this matrix, assuming a row vector convention.
1216  /// Returns the maximum absolute column sum. ie. max_j(sum_i(abs(a_ij)))
1217  T getNormInf() const;
1218 
1219  /// Get the max-norm of this matrix
1220  /// Returns the maximum absolute entry. ie. max_j(max_i(abs(a_ij)))
1221  T getNormMax() const;
1222 
1223  /// Get the spectral norm of this matrix
1224  /// Returns the maximum singular value.
1225  T getNormSpectral() const;
1226 
1227  // I/O methods. Return 0 if read/write successful, -1 if unsuccessful.
1228  int save(std::ostream &os, int binary) const;
1229  bool load(UT_IStream &is);
1230 
1231  void outAsciiNoName(std::ostream &os) const;
1232 
1233  static const UT_Matrix3T<T> &getIdentityMatrix();
1234 
1235  // I/O friends:
1236  friend std::ostream &operator<<(std::ostream &os, const UT_Matrix3T<T> &v)
1237  {
1238  v.writeClassName(os);
1239  v.outAsciiNoName(os);
1240  return os;
1241  }
1242 
1243  /// @{
1244  /// Methods to serialize to a JSON stream. The matrix is stored as an
1245  /// array of 9 reals.
1246  bool save(UT_JSONWriter &w) const;
1247  bool save(UT_JSONValue &v) const;
1248  bool load(UT_JSONParser &p);
1249  /// @}
1250 
1251  /// Returns the vector size
1252  static int entries() { return tuple_size; }
1253 
1254  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
1255  /// order given by a templated UT_XformOrder.
1256  /// @{
1257  template <int ORDER>
1258  void rotate(T rx, T ry, T rz);
1259 
1260  /// If angle_degrees is an exact multiple of 90, it is changed to 0,
1261  /// and the quarter turn number (0-3) is returned. If angle_degrees
1262  /// is *not* an exact multiple of 90, it is left unchanged,
1263  /// and 0 is returned.
1264  static uint reduceExactQuarterTurns(T &angle_degrees);
1265 private:
1266  // Check this matrix to see if it is a valid rotation matrix, and permute
1267  // its elements depending on the rotOrder value in crack(). checkRot()
1268  // returns 0 if OK and 1 otherwise.
1269  SYS_FORCE_INLINE int checkRot() const;
1270 
1271  // Operation to aid in cofactor computation
1273  void coVals(int k, int r[2]) const
1274  {
1275  switch(k)
1276  {
1277  case 0: r[0] = 1; r[1] = 2; break;
1278  case 1: r[0] = 0; r[1] = 2; break;
1279  case 2: r[0] = 0; r[1] = 1; break;
1280  }
1281  }
1282 
1283 
1284  void writeClassName(std::ostream &os) const;
1285  static const char *className();
1286 
1287  inline T distanceSquaredInline(const UT_Matrix3T<T> &m);
1288 
1289  // Return the dot product between two rows i and j:
1290  SYS_FORCE_INLINE T rowDot(unsigned i, unsigned j) const
1291  {
1292  return (i <= 2 && j <= 2) ?
1293  matx[i][0]*matx[j][0] +
1294  matx[i][1]*matx[j][1] +
1295  matx[i][2]*matx[j][2] : (T)0;
1296  }
1297 
1298  // The matrix data:
1299  union {
1300  T matx[3][3];
1301  T myFloats[tuple_size];
1302  };
1303 
1304  // To allow calling private methods from polarDecompose since it forces
1305  // fpreal64 precision.
1306  friend UT_Matrix3T<fpreal32>;
1307  friend UT_Matrix3T<fpreal64>;
1308 };
1309 
1310 #include "UT_Vector3.h"
1311 
1312 template <typename T>
1313 template <typename S>
1314 inline
1316 {
1317  matx[0][0] = matx[0][1] = matx[0][2] = vec.x();
1318  matx[1][0] = matx[1][1] = matx[1][2] = vec.y();
1319  matx[2][0] = matx[2][1] = matx[2][2] = vec.z();
1320  return *this;
1321 }
1322 
1323 template <typename T>
1324 template <typename S>
1325 inline
1327 {
1328  T x = vec.x(); T y = vec.y(); T z = vec.z();
1329  matx[0][0]+=x; matx[0][1]+=x; matx[0][2]+=x;
1330  matx[1][0]+=y; matx[1][1]+=y; matx[1][2]+=y;
1331  matx[2][0]+=z; matx[2][1]+=z; matx[2][2]+=z;
1332  return *this;
1333 }
1334 
1335 template <typename T>
1336 template <typename S>
1337 inline
1339 {
1340  T x = vec.x(); T y = vec.y(); T z = vec.z();
1341  matx[0][0]-=x; matx[0][1]-=x; matx[0][2]-=x;
1342  matx[1][0]-=y; matx[1][1]-=y; matx[1][2]-=y;
1343  matx[2][0]-=z; matx[2][1]-=z; matx[2][2]-=z;
1344  return *this;
1345 }
1346 
1347 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1348 template <> inline UT_Matrix3T<float>&
1350 {
1351  v4uf r0(m.matx[0]);
1352  v4uf r1(m.matx[1]);
1353  v4uf r2(m(2,0), m(2,1), m(2,2), 0.f);
1354 
1355  // Do not alter the order in which the rows are computed.
1356  // This routine relies on overriding
1357  const float m10 = matx[1][0];
1358  const float m20 = matx[2][0];
1359  {
1360  const v4uf row =
1361  r0 * v4uf(matx[0][0])
1362  + r1 * v4uf(matx[0][1])
1363  + r2 * v4uf(matx[0][2]);
1364  vm_store(matx[0], row.vector);
1365  }
1366  {
1367  const v4uf row =
1368  r0 * v4uf(m10)
1369  + r1 * v4uf(matx[1][1])
1370  + r2 * v4uf(matx[1][2]);
1371  vm_store(matx[1], row.vector);
1372  }
1373  {
1374  const v4uf row =
1375  r0 * v4uf(m20)
1376  + r1 * v4uf(matx[2][1])
1377  + r2 * v4uf(matx[2][2]);
1378 
1379  matx[2][0] = row[0];
1380  matx[2][1] = row[1];
1381  matx[2][2] = row[2];
1382  }
1383  return *this;
1384 }
1385 template <> template <> inline UT_Matrix3T<float>&
1387 {
1388  const auto& l = m.lowerTri();
1389 
1390  v4uf r0(l.q00, l.q10, l.q20, 0.f);
1391  v4uf r1(l.q10, l.q11, l.q21, 0.f);
1392  v4uf r2(l.q20, l.q21, l.q22, 0.f);
1393 
1394  // Do not alter the order in which the rows are computed.
1395  // This routine relies on overriding
1396  const float m10 = matx[1][0];
1397  const float m20 = matx[2][0];
1398  {
1399  const v4uf row =
1400  r0 * v4uf(matx[0][0])
1401  + r1 * v4uf(matx[0][1])
1402  + r2 * v4uf(matx[0][2]);
1403  vm_store(matx[0], row.vector);
1404  }
1405  {
1406  const v4uf row =
1407  r0 * v4uf(m10)
1408  + r1 * v4uf(matx[1][1])
1409  + r2 * v4uf(matx[1][2]);
1410  vm_store(matx[1], row.vector);
1411  }
1412  {
1413  const v4uf row =
1414  r0 * v4uf(m20)
1415  + r1 * v4uf(matx[2][1])
1416  + r2 * v4uf(matx[2][2]);
1417 
1418  matx[2][0] = row[0];
1419  matx[2][1] = row[1];
1420  matx[2][2] = row[2];
1421  }
1422  return *this;
1423 }
1424 #endif
1425 
1426 // Scaled outer product update (given scalar b, row vectors v1 and v2)
1427 // this += b * transpose(v1) * v2
1428 template <typename T>
1429 template <typename S>
1430 inline
1432  const UT_Vector3T<S> &v1,
1433  const UT_Vector3T<S> &v2)
1434 {
1435  T bv1;
1436  bv1 = b * v1.x();
1437  matx[0][0]+=bv1*v2.x();
1438  matx[0][1]+=bv1*v2.y();
1439  matx[0][2]+=bv1*v2.z();
1440  bv1 = b * v1.y();
1441  matx[1][0]+=bv1*v2.x();
1442  matx[1][1]+=bv1*v2.y();
1443  matx[1][2]+=bv1*v2.z();
1444  bv1 = b * v1.z();
1445  matx[2][0]+=bv1*v2.x();
1446  matx[2][1]+=bv1*v2.y();
1447  matx[2][2]+=bv1*v2.z();
1448 }
1449 
1450 template <typename T>
1451 inline
1453 {
1454  UT_ASSERT_P(row < 3);
1455  return *(const UT_Vector3T<T>*)(matx[row]);
1456 }
1457 
1458 template <typename T>
1459 inline
1461 {
1462  UT_ASSERT_P(row < 3);
1463  return *(UT_Vector3T<T>*)(matx[row]);
1464 }
1465 
1466 
1467 // Free floating functions:
1468 template <typename T, typename S>
1469 inline
1471 {
1472  return mat+vec;
1473 }
1474 
1475 template <typename T, typename S>
1476 inline
1478 {
1479  return m1*sc;
1480 }
1481 
1482 template <typename T, typename S>
1483 inline
1485 {
1486  return (m1 * (T(1)/scalar));
1487 }
1488 
1489 /// Multiplication of a row or column vector by a matrix (ie. right vs. left
1490 /// multiplication respectively). The operator*() declared above is an alias
1491 /// for rowVecMult(). The functions that take a 4x4 matrix first extend
1492 /// the vector to 4D (with a trailing 1.0 element).
1493 //
1494 // @{
1495 // Notes on optimisation of matrix/vector multiplies:
1496 // - multiply(dest, mat) functions have been deprecated in favour of
1497 // rowVecMult/colVecMult routines, which produce temporaries. For these to
1498 // offer comparable performance, the compiler has to optimize away the
1499 // temporary, but most modern compilers can do this. Performance tests with
1500 // gcc3.3 indicate that this is a realistic expectation for modern
1501 // compilers.
1502 // - since matrix/vector multiplies cannot be done without temporary data,
1503 // the "primary" functions are the global matrix/vector
1504 // rowVecMult/colVecMult routines, rather than the member functions.
1505 // - inlining is explicitly requested only for non-deprecated functions
1506 // involving the native types (UT_Vector3 and UT_Matrix3)
1507 
1508 template <typename T, typename S>
1509 inline UT_Vector3T<T> rowVecMult(const UT_Vector3T<T> &v, const UT_Matrix3T<S> &m);
1510 template <typename T, typename S>
1511 inline UT_Vector3T<T> colVecMult(const UT_Matrix3T<S> &m, const UT_Vector3T<T> &v);
1512 // @}
1513 
1514 template <typename T, typename S>
1515 inline
1517 {
1518  return UT_Vector3T<T>(
1519  v.x()*m(0,0) + v.y()*m(1,0) + v.z()*m(2,0),
1520  v.x()*m(0,1) + v.y()*m(1,1) + v.z()*m(2,1),
1521  v.x()*m(0,2) + v.y()*m(1,2) + v.z()*m(2,2)
1522  );
1523 }
1524 
1525 template <typename T, typename S>
1526 inline
1528 {
1529  return rowVecMult(v, m);
1530 }
1531 
1532 template <typename T, typename S>
1533 inline
1535 {
1536  return UT_Vector3T<T>(
1537  v.x()*m(0,0) + v.y()*m(0,1) + v.z()*m(0,2),
1538  v.x()*m(1,0) + v.y()*m(1,1) + v.z()*m(1,2),
1539  v.x()*m(2,0) + v.y()*m(2,1) + v.z()*m(2,2)
1540  );
1541 }
1542 
1543 template <typename T>
1544 SYS_FORCE_INLINE void
1546 {
1547  operator=(::rowVecMult(*this, m));
1548 }
1549 template <typename T>
1550 SYS_FORCE_INLINE void
1552 {
1553  operator=(::rowVecMult(*this, m));
1554 }
1555 template <typename T>
1556 SYS_FORCE_INLINE void
1558 {
1559  operator=(::colVecMult(m, *this));
1560 }
1561 template <typename T>
1562 SYS_FORCE_INLINE void
1564 {
1565  operator=(::colVecMult(m, *this));
1566 }
1567 template <typename T>
1568 template <typename S>
1571 {
1572  rowVecMult(m);
1573  return *this;
1574 }
1575 template <typename T>
1576 template <typename S>
1577 SYS_FORCE_INLINE void
1579 {
1580  colVecMult(mat);
1581 }
1582 template <typename T>
1583 template <typename S>
1584 SYS_FORCE_INLINE void
1586 {
1587  dest = ::colVecMult(mat, *this);
1588 }
1589 template <typename T>
1590 template <typename S>
1591 SYS_FORCE_INLINE void
1593 {
1594  dest = ::rowVecMult(*this, mat);
1595 }
1596 
1597 template <typename T>
1598 static inline
1599 T dot(const UT_Matrix3T<T> &m1, const UT_Matrix3T<T> &m2){
1600  return m1.dot(m2);
1601 }
1602 
1603 template <typename T>
1604 inline
1606 {
1607  return UT_Matrix3T<T>(
1608  SYSmin(v1(0,0), v2(0,0)),
1609  SYSmin(v1(0,1), v2(0,1)),
1610  SYSmin(v1(0,2), v2(0,2)),
1611  SYSmin(v1(1,0), v2(1,0)),
1612  SYSmin(v1(1,1), v2(1,1)),
1613  SYSmin(v1(1,2), v2(1,2)),
1614  SYSmin(v1(2,0), v2(2,0)),
1615  SYSmin(v1(2,1), v2(2,1)),
1616  SYSmin(v1(2,2), v2(2,2))
1617  );
1618 }
1619 
1620 template <typename T>
1621 inline
1623 {
1624  return UT_Matrix3T<T>(
1625  SYSmax(v1(0,0), v2(0,0)),
1626  SYSmax(v1(0,1), v2(0,1)),
1627  SYSmax(v1(0,2), v2(0,2)),
1628  SYSmax(v1(1,0), v2(1,0)),
1629  SYSmax(v1(1,1), v2(1,1)),
1630  SYSmax(v1(1,2), v2(1,2)),
1631  SYSmax(v1(2,0), v2(2,0)),
1632  SYSmax(v1(2,1), v2(2,1)),
1633  SYSmax(v1(2,2), v2(2,2))
1634  );
1635 }
1636 
1637 template <typename T,typename S>
1638 inline
1640 {
1641  return UT_Matrix3T<T>(
1642  SYSlerp(v1(0,0), v2(0,0), t),
1643  SYSlerp(v1(0,1), v2(0,1), t),
1644  SYSlerp(v1(0,2), v2(0,2), t),
1645  SYSlerp(v1(1,0), v2(1,0), t),
1646  SYSlerp(v1(1,1), v2(1,1), t),
1647  SYSlerp(v1(1,2), v2(1,2), t),
1648  SYSlerp(v1(2,0), v2(2,0), t),
1649  SYSlerp(v1(2,1), v2(2,1), t),
1650  SYSlerp(v1(2,2), v2(2,2), t)
1651  );
1652 }
1653 
1654 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1655 template <>
1656 inline
1658 {
1660  {
1661  const v4uf l(v1.data());
1662  const v4uf r(v2.data());
1663  vm_store(result.data(), SYSlerp(l, r, t).vector);
1664  }
1665  {
1666  const v4uf l(v1.data() + 4);
1667  const v4uf r(v2.data() + 4);
1668  vm_store(result.data() + 4, SYSlerp(l, r, t).vector);
1669  }
1670  {
1671  result(2,2) = SYSlerp(v1(2,2), v2(2,2), t);
1672  }
1673  return result;
1674 }
1675 #endif
1676 
1677 template< typename T, exint D >
1678 class UT_FixedVector;
1679 
1680 template<typename T>
1682 {
1684  typedef T DataType;
1685  static const exint TupleSize = 9;
1686  static const bool isVectorType = true;
1687 };
1688 
1689 // Overload for custom formatting of UT_Matrix3T<T> with UTformat.
1690 template<typename T>
1691 UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix3T<T> &v);
1692 
1693 // UT_Matrix3TFromFixed<T> is a function object that
1694 // creates a UT_Matrix3T<T> from a fixed array-like type TS,
1695 // examples of which include T[9], UT_FixedVector<T,9> and UT_FixedArray<T,9> (AKA std::array<T,9>)
1696 template <typename T>
1698 {
1699  template< typename TS >
1700  constexpr SYS_FORCE_INLINE UT_Matrix3T<T> operator()(const TS& as) const noexcept
1701  {
1702  SYS_STATIC_ASSERT( SYS_IsFixedArrayOf_v< TS, T, 3 * 3 > );
1703 
1704  return UT_Matrix3T<T>{
1705  as[ 0], as[ 1], as[ 2],
1706  as[ 3], as[ 4], as[ 5],
1707  as[ 6], as[ 7], as[ 8]
1708  };
1709  }
1710 };
1711 
1712 // Convert a fixed array-like type TS into a UT_Matrix3T< T >.
1713 // This allows conversion to UT_Matrix3T without fixing T.
1714 // Instead, the element type of TS determines the type T.
1715 template< typename TS >
1717 UTmakeMatrix3T( const TS& as ) noexcept
1718 {
1720 
1721  return UT_Matrix3TFromFixed< T >{}( as );
1722 }
1723 
1724 // UT_FromFixed<V> creates a V from a flat, fixed array-like representation
1725 
1726 // Primary
1727 template <typename V >
1728 struct UT_FromFixed;
1729 
1730 // Partial specialization for UT_Matrix3T
1731 template <typename T>
1733 
1734 template <typename T> template<int ORDER>
1735 void
1736 UT_Matrix3T<T>::rotate(T rx, T ry, T rz)
1737 {
1738  switch(ORDER)
1739  {
1740  case 0://UT_XformOrder::XYZ:
1741  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1742  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1743  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1744  break;
1745 
1746  case 1:
1747  //case UT_XformOrder::XZY:
1748  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1749  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1750  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1751  break;
1752 
1753  case 2:
1754  //case UT_XformOrder::YXZ:
1755  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1756  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1757  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1758  break;
1759 
1760  case 3:
1761  //case UT_XformOrder::YZX:
1762  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1763  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1764  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1765  break;
1766 
1767  case 4:
1768  //case UT_XformOrder::ZXY:
1769  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1770  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1771  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1772  break;
1773 
1774  case 5:
1775  //case UT_XformOrder::ZYX:
1776  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1777  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1778  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1779  break;
1780 
1781  default:
1782  break;
1783  }
1784 }
1785 
1786 #endif
static int entries()
Returns the vector size.
Definition: UT_Matrix3.h:1252
UT_Vector3T< T > rowVecMult(const UT_Vector3T< T > &v, const UT_Matrix3T< S > &m)
Definition: UT_Matrix3.h:1516
SYS_FORCE_INLINE T & operator()(unsigned row, unsigned col) noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:1167
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)
Multiply each element of the given matrix by scalar and return the result.
Definition: Mat3.h:561
SYS_FORCE_INLINE T coFactor(int k, int l) const
Definition: UT_Matrix3.h:564
SYS_FORCE_INLINE UT_Matrix3T< T > & operator/=(T scalar)
Definition: UT_Matrix3.h:407
void leftMult(const UT_SymMatrix3T< S > &m)
Multiply given symmetric matrix on the left.
Definition: UT_Matrix3.h:330
#define SYS_STATIC_ASSERT(expr)
UT_Matrix3T< T > transposedCopy() const
Definition: UT_Matrix3.h:660
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
void leftMult(const UT_Matrix3T< S > &m)
Multiply given matrix3 on the left.
Definition: UT_Matrix3.h:355
constexpr bool operator!=(const UT_Matrix3T< T > &m) const noexcept
Definition: UT_Matrix3.h:385
void orientInverse(const UT_Vector3F &v, T pscale, const UT_Vector3F *s3, const UT_Vector3F *up, const UT_QuaternionF *q)
Definition: UT_Matrix3.h:549
const T * operator()(unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix3.h:1187
SYS_FORCE_INLINE void translate(const UT_Vector2T< T > &delta)
Definition: UT_Matrix3.h:898
SYS_FORCE_INLINE void prerotateQuarter()
Definition: UT_Matrix3.h:796
void UTswap(T &a, T &b)
Definition: UT_Swap.h:35
void scale(T sx, T sy, T sz)
Definition: UT_Matrix3.h:854
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:688
GLboolean invert
Definition: glcorearb.h:549
GLboolean * data
Definition: glcorearb.h:131
const GLdouble * v
Definition: glcorearb.h:837
constexpr bool operator==(const UT_Matrix3T< T > &m) const noexcept
Definition: UT_Matrix3.h:378
SYS_FORCE_INLINE void colVecMult(const UT_Matrix3F &m)
Definition: UT_Matrix3.h:1557
UT_Matrix3T< T > & operator*=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:281
Transformation order of scales, rotates, and translates.
Definition: UT_XformOrder.h:23
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Add corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:577
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:1004
SYS_FORCE_INLINE T operator()(unsigned row, unsigned col) const noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:1173
T determinant() const
Definition: UT_Matrix3.h:578
const GLuint GLenum const void * binary
Definition: glcorearb.h:1924
GA_API const UT_StringHolder rot
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
typename SYS_FixedArrayElement< T >::type SYS_FixedArrayElement_t
void prerotate(const UT_Vector3T< T > &rad, const UT_XformOrder &order)
Definition: UT_Matrix3.h:838
UT_Matrix3T< T > SYSmax(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2)
Definition: UT_Matrix3.h:1622
constexpr SYS_FORCE_INLINE T & z() noexcept
Definition: UT_Vector3.h:667
int64 exint
Definition: SYS_Types.h:125
const LowerTri & lowerTri() const
Return reference to the lower triangular elements for symbolic access.
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix3T< T > &v)
void reverse(I begin, I end)
Definition: pugixml.cpp:7190
GLdouble s
Definition: glad.h:3009
SYS_FORCE_INLINE UT_Matrix3T< T > & operator+=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:249
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:87
#define UT_API
Definition: UT_API.h:14
Generic symmetric 3x3 matrix.
Definition: UT_SymMatrix3.h:27
GLint y
Definition: glcorearb.h:103
T * operator()(unsigned row)
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix3.h:1182
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:37
void extractScales(UT_Vector3T< fpreal16 > &scales, UT_Vector3T< fpreal16 > *shears=0)
Definition: UT_Matrix3.h:1006
void prescale(T sx, T sy, T sz)
Definition: UT_Matrix3.h:867
**But if you need a result
Definition: thread.h:613
static const exint TupleSize
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:818
GLdouble GLdouble GLdouble q
Definition: glad.h:2445
void orient(const UT_Vector3D &v, T pscale, const UT_Vector3D *s3, const UT_Vector3D *up, const UT_QuaternionD *q)
Definition: UT_Matrix3.h:539
UT_Matrix3T< T > SYSmin(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2)
Definition: UT_Matrix3.h:1605
constexpr SYS_FORCE_INLINE UT_Vector3T & operator*=(const T &a) noexcept
Definition: UT_Vector3.h:326
2D Vector class.
Definition: UT_Vector2.h:159
void transpose()
Definition: UT_Matrix3.h:653
const T * data() const
Return the raw matrix data.
Definition: UT_Matrix3.h:1158
SYS_FORCE_INLINE void pretranslate(const UT_Vector2T< T > &delta)
Definition: UT_Matrix3.h:911
SYS_FORCE_INLINE void rotateQuarter()
Definition: UT_Matrix3.h:726
SYS_FORCE_INLINE void prescale(const UT_Vector3T< T > &s)
Definition: UT_Matrix3.h:874
double fpreal64
Definition: SYS_Types.h:201
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)
Bilinear interpolation.
Definition: UT_Matrix3.h:72
SYS_FORCE_INLINE void outerproductUpdate(T b, const UT_Vector3F &v1, const UT_Vector3F &v2)
Definition: UT_Matrix3.h:428
GA_API const UT_StringHolder scale
SYS_FORCE_INLINE void shear(const UT_Vector3T< T > &sh)
Definition: UT_Matrix3.h:1052
GLfloat f
Definition: glcorearb.h:1926
SYS_FORCE_INLINE void negate()
Negates this matrix, i.e. multiplies it by -1.
Definition: UT_Matrix3.h:879
SYS_FORCE_INLINE void multiplyT(const UT_Matrix3T< S > &mat)
Definition: UT_Matrix3.h:1578
Definition: core.h:760
bool isEqual(const UT_Matrix3T< T > &m, T tolerance=T(SYS_FTOLERANCE)) const
Check for equality within a tolerance level.
Definition: UT_Matrix3.h:668
void identity()
Set the matrix to identity.
Definition: UT_Matrix3.h:1128
UT_Matrix3T< T > SYSlerp(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2, S t)
Definition: UT_Matrix3.h:1639
constexpr UT_Matrix3T< SYS_FixedArrayElement_t< TS > > UTmakeMatrix3T(const TS &as) noexcept
Definition: UT_Matrix3.h:1717
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Subtract corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:587
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4369
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
SYS_FORCE_INLINE void scale(const UT_Vector3T< T > &s)
Definition: UT_Matrix3.h:861
bool isIdentity() const
Definition: UT_Matrix3.h:1132
class UT_API UT_Matrix3T
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
Definition: CE_Vector.h:130
static const bool isVectorType
void outerproductUpdateT(T b, const UT_Vector3T< S > &v1, const UT_Vector3T< S > &v2)
Definition: UT_Matrix3.h:1431
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
UT_Matrix3T< T > SYSbarycentric(const UT_Matrix3T< T > &v0, const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2, S u, S v)
Barycentric interpolation.
Definition: UT_Matrix3.h:79
T matx[3][3]
Definition: UT_Matrix3.h:1300
Definition: VM_SIMD.h:188
SYS_FORCE_INLINE void rowVecMult(const UT_Matrix3F &m)
Definition: UT_Matrix3.h:1545
SYS_FORCE_INLINE void outerproductUpdate(T b, const UT_Vector3D &v1, const UT_Vector3D &v2)
Definition: UT_Matrix3.h:433
GLdouble GLdouble GLint GLint order
Definition: glad.h:2676
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:109
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLint GLenum GLint x
Definition: glcorearb.h:409
void orientInverse(const UT_Vector3D &v, T pscale, const UT_Vector3D *s3, const UT_Vector3D *up, const UT_QuaternionD *q)
Definition: UT_Matrix3.h:554
ImageBuf OIIO_API rotate(const ImageBuf &src, float angle, string_view filtername=string_view(), float filterwidth=0.0f, bool recompute_roi=false, ROI roi={}, int nthreads=0)
void translate(T dx, T dy)
Definition: UT_Matrix3.h:888
GA_API const UT_StringHolder orient
IMATH_HOSTDEVICE const Vec2< S > & operator*=(Vec2< S > &v, const Matrix22< T > &m) IMATH_NOEXCEPT
Vector-matrix multiplication: v *= m.
Definition: ImathMatrix.h:4660
GLdouble t
Definition: glad.h:2397
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:303
SYS_FORCE_INLINE void rotateHalf()
Definition: UT_Matrix3.h:749
GLfloat v0
Definition: glcorearb.h:816
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:1452
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:1069
void shear(T s_xy, T s_xz, T s_yz)
Definition: UT_Matrix3.h:1040
Inner class to access the elements symbolically.
IFDmantra py
Definition: HDK_Image.dox:266
GLint j
Definition: glad.h:2733
Quaternion class.
Definition: GEO_Detail.h:48
static UT_Matrix3T< T > reflectMat(const UT_Vector3T< S > &plane_normal)
Definition: UT_Matrix3.h:443
GA_API const UT_StringHolder up
bool isSymmetric(const MatType &m)
Determine if a matrix is symmetric.
Definition: Mat.h:880
constexpr SYS_FORCE_INLINE UT_Matrix3T< T > operator()(const TS &as) const noexcept
Definition: UT_Matrix3.h:1700
SYS_FORCE_INLINE UT_Matrix3T< T > & operator-=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:265
void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
Definition: UT_Matrix3.h:1002
UT_Vector3T< T > colVecMult(const UT_Matrix3T< S > &m, const UT_Vector3T< T > &v)
Definition: UT_Matrix3.h:1534
GLfloat GLfloat v1
Definition: glcorearb.h:817
GLuint GLfloat * val
Definition: glcorearb.h:1608
GA_API const UT_StringHolder pscale
unsigned hash() const
Compute a hash.
Definition: UT_Matrix3.h:1163
int decompose(const math::Mat4< T > &m, math::Vec3< T > &scale, math::Vec3< T > &rotate, math::Vec3< T > &translate)
Decompose an affine transform into scale, rotation (XYZ order), and translation components.
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:99
GU_API void solve(const GU_Detail &gdp_a, const GA_Range &pts_a, const GU_Detail &gdp_b, const GA_Range &pts_b, Method method, bool compute_distortion, Result &result)
SYS_FORCE_INLINE void addScaledMat(T k, const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:234
bool isAlmostEqual(const UT_Matrix3T< T > &m, int ulps=50) const
Definition: UT_Matrix3.h:684
T getEuclideanNorm() const
Definition: UT_Matrix3.h:1202
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4392
void orient(const UT_Vector3F &v, T pscale, const UT_Vector3F *s3, const UT_Vector3F *up, const UT_QuaternionF *q)
Definition: UT_Matrix3.h:534
#define SYS_FTOLERANCE
Definition: SYS_Types.h:208
void zero()
Set the matrix to zero.
Definition: UT_Matrix3.h:1130
GLubyte GLubyte GLubyte GLubyte w
Definition: glcorearb.h:857
GLenum GLenum GLsizei void * row
Definition: glad.h:5135
void conditionRotate(UT_Vector3F *scales=0)
Definition: UT_Matrix3.h:989
void conditionRotate(UT_Vector3D *scales)
Definition: UT_Matrix3.h:991
GLboolean r
Definition: glcorearb.h:1222
#define const
Definition: zconf.h:214
void rotate(UT_Vector3T< S > &axis, T theta, int norm=1)
PUGI__FN char_t * translate(char_t *buffer, const char_t *from, const char_t *to, size_t to_length)
Definition: pugixml.cpp:8352
T dot(unsigned i, unsigned j) const
Definition: UT_Matrix3.h:1122
SYS_FORCE_INLINE void prerotateHalf()
Definition: UT_Matrix3.h:822
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector3.h:665
SYS_FORCE_INLINE void multiply(UT_Vector3T< T > &dest, const UT_Matrix4T< S > &mat) const
Definition: UT_Matrix4.h:2097
bool SYSisEqual(const UT_Vector2T< T > &a, const UT_Vector2T< T > &b, S tol=SYS_FTOLERANCE)
Componentwise equality.
Definition: UT_Vector2.h:674
UT_Matrix3T< T > operator/(const UT_Matrix3T< T > &mat, S sc)
Definition: UT_Matrix3.h:1484
SYS_FORCE_INLINE void rotateWithQTurns(T theta, uint qturns)
Definition: UT_Matrix3.h:764
bool isZero() const
Definition: UT_Matrix3.h:1144
void pretranslate(T dx, T dy)
Definition: UT_Matrix3.h:904
UT_FixedVector< T, 9 > FixedVectorType
Definition: UT_Matrix3.h:1683
unsigned int uint
Definition: SYS_Types.h:45
T trace() const
Definition: UT_Matrix3.h:584
v4sf vector
Definition: VM_SIMD.h:348
void rotate(const UT_Vector3T< T > &rad, const UT_XformOrder &ord)
Definition: UT_Matrix3.h:848
SYS_FORCE_INLINE UT_Matrix3T< T > & operator*=(T scalar)
Definition: UT_Matrix3.h:399
bool isLowerTriangular(T tolerance=T(SYS_FTOLERANCE)) const
Check for lower triangular within a tolerance level to 0.
Definition: UT_Matrix3.h:703
T * data()
Return the raw matrix data.
Definition: UT_Matrix3.h:1159
GLenum src
Definition: glcorearb.h:1793
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:663