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