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_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>
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 const 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  /// Arbitrary UT_FixedVector of the same size
126  template <typename S,bool INST>
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  template <typename S,bool INST>
137  const UT_FixedVector<S,3,INST> &r0,
138  const UT_FixedVector<S,3,INST> &r1,
139  const UT_FixedVector<S,3,INST> &r2) noexcept
140  : matx{
141  {r0[0],r0[1],r0[2]},
142  {r1[0],r1[1],r1[2]},
143  {r2[0],r2[1],r2[2]}}
144  {}
145 
146  /// This constructor is for convenience.
147  constexpr UT_Matrix3T(
148  T val00, T val01, T val02,
149  T val10, T val11, T val12,
150  T val20, T val21, T val22) noexcept
151  : matx{
152  {val00,val01,val02},
153  {val10,val11,val12},
154  {val20,val21,val22}}
155  {}
156 
157  /// Base type conversion constructor
158  template <typename S>
159  UT_Matrix3T(const UT_Matrix3T<S> &m) noexcept
160  : matx{
161  {T(m(0,0)),T(m(0,1)),T(m(0,2))},
162  {T(m(1,0)),T(m(1,1)),T(m(1,2))},
163  {T(m(2,0)),T(m(2,1)),T(m(2,2))}}
164  {}
165  explicit UT_Matrix3T(const UT_Matrix4T<fpreal32> &m);
166  explicit UT_Matrix3T(const UT_Matrix4T<fpreal64> &m);
167 
168  /// Construct from a symmetric 3x3 matrix
169  template <typename S>
171  {
172  this->operator=(m);
173  }
174 
175  /// Default copy assignment operator
176  UT_Matrix3T<T> &operator=(const UT_Matrix3T<T> &m) = default;
177 
178  /// Default move assignment operator
179  UT_Matrix3T<T> &operator=(UT_Matrix3T<T> &&m) = default;
180 
181  /// Conversion operator that returns a 3x3 from a 4x4 matrix by ignoring the
182  /// last row and last column.
183  /// @{
184  UT_Matrix3T<T> &operator=(const UT_Matrix4T<fpreal32> &m);
185  UT_Matrix3T<T> &operator=(const UT_Matrix4T<fpreal64> &m);
186  /// @}
187  template <typename S>
189  {
190  matx[0][0]=m(0,0); matx[0][1]=m(0,1); matx[0][2]=m(0,2);
191  matx[1][0]=m(1,0); matx[1][1]=m(1,1); matx[1][2]=m(1,2);
192  matx[2][0]=m(2,0); matx[2][1]=m(2,1); matx[2][2]=m(2,2);
193  return *this;
194  }
195 
196  /// Convert from a symmetric matrix to non-symmetric.
197  template <typename S>
199  {
200  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
201  const LowerTri &l = m.lowerTri();
202  matx[0][0] = l.q00; matx[0][1] = l.q10; matx[0][2] = l.q20;
203  matx[1][0] = l.q10; matx[1][1] = l.q11; matx[1][2] = l.q21;
204  matx[2][0] = l.q20; matx[2][1] = l.q21; matx[2][2] = l.q22;
205  return *this;
206  }
207 
208  /// Convert this to a symmetric matrix, using the lower-triangular portion
210  {
211  return UT_SymMatrix3T<T>(matx[0][0],
212  matx[1][0], matx[1][1],
213  matx[2][0], matx[2][1], matx[2][2]);
214  }
215 
216  /// Convert this to a symmetric matrix, using the upper-triangular portion
218  {
219  return UT_SymMatrix3T<T>(matx[0][0],
220  matx[0][1], matx[1][1],
221  matx[0][2], matx[1][2], matx[2][2]);
222  }
223 
224  /// Convert this to a symmetric matrix, using averaged components
226  {
227  return UT_SymMatrix3T<T>(matx[0][0],
228  (matx[0][1] + matx[1][0]) / 2,
229  matx[1][1],
230  (matx[0][2] + matx[2][0]) / 2,
231  (matx[1][2] + matx[2][1]) / 2,
232  matx[2][2]);
233  }
234 
236  {
237  return UT_Matrix3T<T>(-matx[0][0], -matx[0][1], -matx[0][2],
238  -matx[1][0], -matx[1][1], -matx[1][2],
239  -matx[2][0], -matx[2][1], -matx[2][2]);
240  }
241 
242  // Does += k * m
244  void addScaledMat(T k, const UT_Matrix3T<T> &m)
245  {
246  matx[0][0]+=k*m.matx[0][0];
247  matx[0][1]+=k*m.matx[0][1];
248  matx[0][2]+=k*m.matx[0][2];
249 
250  matx[1][0]+=k*m.matx[1][0];
251  matx[1][1]+=k*m.matx[1][1];
252  matx[1][2]+=k*m.matx[1][2];
253 
254  matx[2][0]+=k*m.matx[2][0];
255  matx[2][1]+=k*m.matx[2][1];
256  matx[2][2]+=k*m.matx[2][2];
257  }
260  {
261  matx[0][0]+=m.matx[0][0];
262  matx[0][1]+=m.matx[0][1];
263  matx[0][2]+=m.matx[0][2];
264 
265  matx[1][0]+=m.matx[1][0];
266  matx[1][1]+=m.matx[1][1];
267  matx[1][2]+=m.matx[1][2];
268 
269  matx[2][0]+=m.matx[2][0];
270  matx[2][1]+=m.matx[2][1];
271  matx[2][2]+=m.matx[2][2];
272  return *this;
273  }
276  {
277  matx[0][0]-=m.matx[0][0];
278  matx[0][1]-=m.matx[0][1];
279  matx[0][2]-=m.matx[0][2];
280 
281  matx[1][0]-=m.matx[1][0];
282  matx[1][1]-=m.matx[1][1];
283  matx[1][2]-=m.matx[1][2];
284 
285  matx[2][0]-=m.matx[2][0];
286  matx[2][1]-=m.matx[2][1];
287  matx[2][2]-=m.matx[2][2];
288  return *this;
289  }
290 
292  {
293  T a, b, c;
294  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
295  matx[0][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
296  matx[0][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
297  matx[0][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
298 
299  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
300  matx[1][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
301  matx[1][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
302  matx[1][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
303 
304  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
305  matx[2][0] = a*m(0,0) + b*m(1,0) + c*m(2,0);
306  matx[2][1] = a*m(0,1) + b*m(1,1) + c*m(2,1);
307  matx[2][2] = a*m(0,2) + b*m(1,2) + c*m(2,2);
308  return *this;
309  }
310 
311  /// Multiply given symmetric matrix on the right
312  template <typename S>
314  {
315  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
316 
317  const LowerTri& l = m.lowerTri();
318  T a, b, c;
319 
320  a = matx[0][0]; b = matx[0][1]; c = matx[0][2];
321  matx[0][0] = a*l.q00 + b*l.q10 + c*l.q20;
322  matx[0][1] = a*l.q10 + b*l.q11 + c*l.q21;
323  matx[0][2] = a*l.q20 + b*l.q21 + c*l.q22;
324 
325  a = matx[1][0]; b = matx[1][1]; c = matx[1][2];
326  matx[1][0] = a*l.q00 + b*l.q10 + c*l.q20;
327  matx[1][1] = a*l.q10 + b*l.q11 + c*l.q21;
328  matx[1][2] = a*l.q20 + b*l.q21 + c*l.q22;
329 
330  a = matx[2][0]; b = matx[2][1]; c = matx[2][2];
331  matx[2][0] = a*l.q00 + b*l.q10 + c*l.q20;
332  matx[2][1] = a*l.q10 + b*l.q11 + c*l.q21;
333  matx[2][2] = a*l.q20 + b*l.q21 + c*l.q22;
334 
335  return *this;
336  }
337 
338  /// Multiply given symmetric matrix on the left
339  template <typename S>
341  {
342  typedef typename UT_SymMatrix3T<S>::LowerTri LowerTri;
343 
344  const LowerTri& l = m.lowerTri();
345  T a, b, c;
346 
347  a = matx[0][0]; b = matx[1][0]; c = matx[2][0];
348  matx[0][0] = a*l.q00 + b*l.q10 + c*l.q20;
349  matx[1][0] = a*l.q10 + b*l.q11 + c*l.q21;
350  matx[2][0] = a*l.q20 + b*l.q21 + c*l.q22;
351 
352  a = matx[0][1]; b = matx[1][1]; c = matx[2][1];
353  matx[0][1] = a*l.q00 + b*l.q10 + c*l.q20;
354  matx[1][1] = a*l.q10 + b*l.q11 + c*l.q21;
355  matx[2][1] = a*l.q20 + b*l.q21 + c*l.q22;
356 
357  a = matx[0][2]; b = matx[1][2]; c = matx[2][2];
358  matx[0][2] = a*l.q00 + b*l.q10 + c*l.q20;
359  matx[1][2] = a*l.q10 + b*l.q11 + c*l.q21;
360  matx[2][2] = a*l.q20 + b*l.q21 + c*l.q22;
361  }
362 
363  /// Multiply given matrix3 on the left
364  template <typename S>
365  void leftMult(const UT_Matrix3T<S> &m)
366  {
367  T a, b, c;
368 
369  a = matx[0][0]; b = matx[1][0]; c = matx[2][0];
370  matx[0][0] = a*m(0,0) + b*m(0,1) + c*m(0,2);
371  matx[1][0] = a*m(1,0) + b*m(1,1) + c*m(1,2);
372  matx[2][0] = a*m(2,0) + b*m(2,1) + c*m(2,2);
373 
374  a = matx[0][1]; b = matx[1][1]; c = matx[2][1];
375  matx[0][1] = a*m(0,0) + b*m(0,1) + c*m(0,2);
376  matx[1][1] = a*m(1,0) + b*m(1,1) + c*m(1,2);
377  matx[2][1] = a*m(2,0) + b*m(2,1) + c*m(2,2);
378 
379  a = matx[0][2]; b = matx[1][2]; c = matx[2][2];
380  matx[0][2] = a*m(0,0) + b*m(0,1) + c*m(0,2);
381  matx[1][2] = a*m(1,0) + b*m(1,1) + c*m(1,2);
382  matx[2][2] = a*m(2,0) + b*m(2,1) + c*m(2,2);
383  }
384 
385  void multiply3(const UT_Matrix4 &m);
386  void multiply3(const UT_DMatrix4 &m);
387 
388  constexpr bool operator==(const UT_Matrix3T<T> &m) const noexcept
389  {
390  return (&m == this) || (
391  matx[0][0]==m(0,0) && matx[0][1]==m(0,1) && matx[0][2]==m(0,2) &&
392  matx[1][0]==m(1,0) && matx[1][1]==m(1,1) && matx[1][2]==m(1,2) &&
393  matx[2][0]==m(2,0) && matx[2][1]==m(2,1) && matx[2][2]==m(2,2) );
394  }
395  constexpr bool operator!=(const UT_Matrix3T<T> &m) const noexcept
396  {
397  return !(*this == m);
398  }
399 
400  // Scalar operators:
401  UT_Matrix3T<T> &operator= (T val)
402  {
403  matx[0][0] = val; matx[0][1] = 0; matx[0][2] = 0;
404  matx[1][0] = 0; matx[1][1] = val; matx[1][2] = 0;
405  matx[2][0] = 0; matx[2][1] = 0; matx[2][2] = val;
406  return *this;
407  }
410  {
411  matx[0][0]*=scalar; matx[0][1]*=scalar; matx[0][2]*=scalar;
412  matx[1][0]*=scalar; matx[1][1]*=scalar; matx[1][2]*=scalar;
413  matx[2][0]*=scalar; matx[2][1]*=scalar; matx[2][2]*=scalar;
414  return *this;
415  }
418  {
419  return operator*=( 1.0f/scalar );
420  }
421 
422  // Vector3 operators:
423  template <typename S>
424  inline UT_Matrix3T<T> &operator= (const UT_Vector3T<S> &vec);
425  template <typename S>
426  inline UT_Matrix3T<T> &operator+=(const UT_Vector3T<S> &vec);
427  template <typename S>
428  inline UT_Matrix3T<T> &operator-=(const UT_Vector3T<S> &vec);
429 
430  /// Scaled outer product update (given scalar b, row vectors v1 and v2)
431  /// this += b * transpose(v1) * v2
432  /// @{
433  template <typename S>
434  inline void outerproductUpdateT(T b,
435  const UT_Vector3T<S> &v1,
436  const UT_Vector3T<S> &v2);
439  const UT_Vector3F &v1,
440  const UT_Vector3F &v2)
441  { outerproductUpdateT(b, v1, v2); }
444  const UT_Vector3D &v1,
445  const UT_Vector3D &v2)
446  { outerproductUpdateT(b, v1, v2); }
447  /// @}
448 
449  // Other matrix operations:
450  // Computes the basis of a 3x3 matrix. This is used by OBB code
451  // to determine what orientation of a bounding box best represents
452  // a cloud of points. To do this, first fill this matrix with
453  // the sum of p*pT for all points in the cloud.
454  // The result is in this matrix itself.
455  void getBasis();
456 
457  // Sets this matrix to the canonical 180 rotation matrix (about the y axis).
458  void arbitrary180rot();
459 
460  // Sets this matrix to an arbitrary rotation matrix that would flip v.
461  // This rotation is used in orient() and dihedral() functions when given two
462  // opposing vectors.
463  template <typename S>
464  void arbitrary180rot(const UT_Vector3T<S>& v);
465 
466  /// Compute the dihedral: return the matrix that computes the rotation
467  /// around the axes normal to both a and b, (their cross product), by the
468  /// angle which is between a and b. The resulting matrix maps a onto b. If
469  /// a and b have the same direction, what comes out is the identity matrix.
470  /// If a and b are opposed, the rotation is undefined and the method
471  /// returns a vector c of zeroes (check with !c); if all is OK, c != 0.
472  /// The transformation is a symmetry around vector a, then a symmetry
473  /// around (norm(a) and norm(b)). If a or b needs to be normalized, pass a
474  /// non-zero value in norm.
475  /// The second function places the result in 'm', and returns 0 if a and b
476  /// are not opposed; otherwise, it returns 1.
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(void)
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  /// WARNING: The non-const method changes the matrix!
917  /// @{
918  template <typename S>
919  int crack(UT_Vector3T<S> &rvec, const UT_XformOrder &order,
920  int remove_scales=1);
921  template <typename S>
922  int crack(UT_Vector3T<S> &rvec, const UT_XformOrder &order,
923  int remove_scales=1) const;
924  template <typename S>
925  int crack2D(S &r) const;
926  /// @}
927 
928  /// Perform the polar decomposition M into an orthogonal matrix Q and an
929  /// symmetric positive-semidefinite matrix S. This is more useful than
930  /// crack() or conditionRotate() when the desire is to blend transforms.
931  /// By default, it gives M=SQ, a left polar decomposition. If reverse is
932  /// false, then it gives M=QS, a right polar decomposition.
933  /// @pre *this is non-singular
934  /// @post *this = Q, and if stretch != 0: *stretch = S
935  /// @return True if successful
936  bool polarDecompose(
937  UT_Matrix3T<T> *stretch = nullptr,
938  bool reverse = true,
939  const int max_iter = 64,
940  const T rel_tol = FLT_EPSILON);
941 
942  /// Turn this matrix into the "closest" rotation matrix.
943  ///
944  /// It uses polarDecompose and then negates the matrix and stretch
945  /// if there is a negative determinant (scale). It returns false iff
946  /// polarDecompose failed, possibly due to a singular matrix.
947  ///
948  /// This is currently the one true way to turn an arbitrary
949  /// matrix into a rotation matrix. If that ever changes,
950  /// put a warning here, and you may want to update
951  /// UT_Matrix4::makeRigidMatrix too.
952  bool makeRotationMatrix(
953  UT_Matrix3T<T> *stretch = nullptr,
954  bool reverse = true,
955  const int max_iter = 64,
956  const T rel_tol = FLT_EPSILON);
957 
958  /// This method will condition the matrix so that it's a valid rotation
959  /// matrix (i.e. crackable). Ideally, the scales should be removed first,
960  /// but this method will attempt to do this as well. It will return the
961  /// conditioned scales if a vector is passed in.
962  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
963  /// @{
964  template <typename S>
965  void conditionRotateT(UT_Vector3T<S> *scales);
966  void conditionRotate(UT_Vector3F *scales=0)
967  { conditionRotateT(scales); }
969  { conditionRotateT(scales); }
970  /// @}
971 
972  /// Extract scales and shears leaving this as an orthogonal rotation matrix
973  /// using the transform order Scales * Shears * Rotate.
974  /// @note The shears are in the order [XY, XZ, YZ]
975  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
976  /// @{
977  template <typename S>
978  void extractScalesT(UT_Vector3T<S> &scales, UT_Vector3T<S> *shears);
979  void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
980  { extractScalesT(scales, shears); }
981  void extractScales(UT_Vector3F &scales, UT_Vector3F *shears=0)
982  { extractScalesT(scales, shears); }
984  UT_Vector3T<fpreal16> *shears=0)
985  { extractScalesT(scales, shears); }
986  /// @}
987 
988  /// Extract scales and shears leaving this as an orthogonal rotation matrix
989  /// (assuming it was only a 2D xform to begin with) using the transform
990  /// order Rotate * Scales * Shears. The shears are XY.
991  template <typename S>
992  void extractScales2D(UT_Vector2T<S> &scales, S *shears=0);
993 
994  /// Extract scales and shears leaving this as an orthogonal rotation matrix
995  /// using the transform order Rotate * Scales * Shears.
996  /// @note The shears are in the order [XY, XZ, YZ]
997  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
998  template <typename S>
999  void rightExtractScales(UT_Vector3T<S> &scales,
1000  UT_Vector3T<S> *shears = nullptr);
1001 
1002  /// Extract scales and shears leaving this as an orthogonal rotation matrix
1003  /// (assuming it was only a 2D xform to begin with) using the transform
1004  /// order Scales * Shears * Rotate. The shears are XY.
1005  template <typename S>
1006  void rightExtractScales2D(UT_Vector2T<S> &scales,
1007  S *shears = nullptr);
1008 
1009  // Shear the matrix according to the values. This is equivalent to
1010  // multiplying the matrix by the shear matrix with the given value.
1011  void shearXY(T val);
1012  void shearXZ(T val);
1013  void shearYZ(T val);
1014 
1015  /// Post-multiply this matrix by the shear matrix formed by (sxy, sxz, syz)
1016  /// @{
1017  void shear(T s_xy, T s_xz, T s_yz)
1018  {
1019  matx[0][0] += matx[0][1]*s_xy + matx[0][2]*s_xz;
1020  matx[0][1] += matx[0][2]*s_yz;
1021 
1022  matx[1][0] += matx[1][1]*s_xy + matx[1][2]*s_xz;
1023  matx[1][1] += matx[1][2]*s_yz;
1024 
1025  matx[2][0] += matx[2][1]*s_xy + matx[2][2]*s_xz;
1026  matx[2][1] += matx[2][2]*s_yz;
1027  }
1029  void shear(const UT_Vector3T<T> &sh)
1030  { shear(sh(0), sh(1), sh(2)); }
1031  /// @}
1032 
1033  // Solve a 3x3 system of equations whose parameters are held in this
1034  // matrix, and whose rhs constants are cx, cy, and cz. The method returns
1035  // 0 if the determinant is not 0, and 1 otherwise.
1036  template <typename S>
1037  int solve(T cx, T cy, T cz,
1038  UT_Vector3T<S> &result) const;
1039 
1040  // Space change operation: right multiply this matrix by the 3x3 matrix
1041  // of the transformation which moves the vector space defined by
1042  // (iSrc, jSrc, cross(iSrc,jSrc)) into the space defined by
1043  // (iDest, jDest, cross(iDest,jDest)). iSrc, jSrc, iDest, and jDest will
1044  // be normalized before the operation if norm is 1. This matrix transforms
1045  // iSrc into iDest, and jSrc into jDest.
1046  template <typename S>
1047  void changeSpace(UT_Vector3T<S> &iSrc, UT_Vector3T<S> &jSrc,
1048  UT_Vector3T<S> &iDest,UT_Vector3T<S> &jDest,
1049  int norm=1);
1050 
1051  // Multiply this matrix by the general transform matrix built from
1052  // translations (tx,ty), degree rotation (rz), scales (sx,sy),
1053  // and possibly a pivot point (px,py). The second methos leaves us
1054  // unchanged, and returns a new (this*xform) instead. The order of the
1055  // multiplies (SRT, RST, Rz, etc) is stored in 'order'. Normally you
1056  // will ignore the 'reverse' parameter, which tells us to build the
1057  // matrix from last to first xform, and to apply some inverses to
1058  // txy, rz, and sxy.
1059  void xform(const UT_XformOrder &order,
1060  T tx=0.0f, T ty=0.0f, T rz=0.0f,
1061  T sx=1.0f, T sy=1.0f,T px=0.0f,T py=0.0f,
1062  int reverse=0);
1063 
1064  // this version handles shears as well
1065  void xform(const UT_XformOrder &order,
1066  T tx, T ty, T rz,
1067  T sx, T sy, T s_xy,
1068  T px, T py,
1069  int reverse=0);
1070 
1071  // Right multiply this matrix by a 3x3 matrix which scales by a given
1072  // amount along the direction of vector v. When applied to a vector w,
1073  // the stretched matrix (*this) stretches w in v by the amount given.
1074  // If norm is non-zero, v will be normalized prior to the operation.
1075  template <typename S>
1076  void stretch(UT_Vector3T<S> &v, T amount, int norm=1);
1077  template <typename S>
1078  SYS_DEPRECATED(12.0) UT_Matrix3T<T> stretch(UT_Vector3T<S> &v, T amount, int norm=1) const;
1079 
1080  //
1081  // This does a test to see if a vector transformed by the matrix
1082  // will maintain it's length (i.e. there are no scales in the matrix)
1083  int isNormalized() const;
1084 
1085  // Return the dot product between two rows i and j:
1086  T dot(unsigned i, unsigned j) const
1087  {
1088  return (i <= 2 && j <= 2) ?
1089  matx[i][0]*matx[j][0] + matx[i][1]*matx[j][1] +
1090  matx[i][2]*matx[j][2] : (T)0;
1091  }
1092 
1093  /// Set the matrix to identity
1094  void identity() { *this = 1; }
1095  /// Set the matrix to zero
1096  void zero() { *this = 0; }
1097 
1098  int isIdentity() const
1099  {
1100  // NB: DO NOT USE TOLERANCES
1101  return(
1102  matx[0][0]==1.0f && matx[0][1]==0.0f &&
1103  matx[0][2]==0.0f && matx[1][0]==0.0f &&
1104  matx[1][1]==1.0f && matx[1][2]==0.0f &&
1105  matx[2][0]==0.0f && matx[2][1]==0.0f &&
1106  matx[2][2]==1.0f
1107  );
1108  }
1109 
1110  int isZero() const
1111  {
1112  // NB: DO NOT USE TOLERANCES
1113  return (
1114  matx[0][0]==0.0f && matx[0][1]==0.0f &&
1115  matx[0][2]==0.0f && matx[1][0]==0.0f &&
1116  matx[1][1]==0.0f && matx[1][2]==0.0f &&
1117  matx[2][0]==0.0f && matx[2][1]==0.0f &&
1118  matx[2][2]==0.0f
1119  );
1120  }
1121 
1122  /// Return the raw matrix data.
1123  // @{
1124  const T *data(void) const { return myFloats; }
1125  T *data(void) { return myFloats; }
1126  // @}
1127 
1128  /// Compute a hash
1129  unsigned hash() const { return SYSvector_hash(data(), tuple_size); }
1130 
1131  /// Return a matrix entry. No bounds checking on subscripts.
1132  // @{
1133  SYS_FORCE_INLINE T &operator()(unsigned row, unsigned col) noexcept
1134  {
1135  UT_ASSERT_P(row < 3 && col < 3);
1136  return matx[row][col];
1137  }
1139  T operator()(unsigned row, unsigned col) const noexcept
1140  {
1141  UT_ASSERT_P(row < 3 && col < 3);
1142  return matx[row][col];
1143  }
1144  // @}
1145 
1146  /// Return a matrix row. No bounds checking on subscript.
1147  // @{
1148  T *operator()(unsigned row)
1149  {
1150  UT_ASSERT_P(row < 3);
1151  return matx[row];
1152  }
1153  const T *operator()(unsigned row) const
1154  {
1155  UT_ASSERT_P(row < 3);
1156  return matx[row];
1157  }
1158  inline const UT_Vector3T<T> &operator[](unsigned row) const;
1159  inline UT_Vector3T<T> &operator[](unsigned row);
1160  // @}
1161 
1162  /// Euclidean or Frobenius norm of a matrix.
1163  /// Does sqrt(sum(a_ij ^2))
1165  { return SYSsqrt(getEuclideanNorm2()); }
1166  /// Euclidean norm squared.
1167  T getEuclideanNorm2() const;
1168 
1169  /// Get the squared Euclidean distance between '*this' and 'from'
1170  /// Returns sum_ij(sqr(b_ij-a_ij))
1171  T distanceSquared(const UT_Matrix3T<T> &src);
1172 
1173  /// Get the 1-norm of this matrix, assuming a row vector convention.
1174  /// Returns the maximum absolute row sum. ie. max_i(sum_j(abs(a_ij)))
1175  T getNorm1() const;
1176 
1177  /// Get the inf-norm of this matrix, assuming a row vector convention.
1178  /// Returns the maximum absolute column sum. ie. max_j(sum_i(abs(a_ij)))
1179  T getNormInf() const;
1180 
1181  // I/O methods. Return 0 if read/write successful, -1 if unsuccessful.
1182  int save(std::ostream &os, int binary) const;
1183  bool load(UT_IStream &is);
1184 
1185  void outAsciiNoName(std::ostream &os) const;
1186 
1187  static const UT_Matrix3T<T> &getIdentityMatrix();
1188 
1189  // I/O friends:
1190  friend std::ostream &operator<<(std::ostream &os, const UT_Matrix3T<T> &v)
1191  {
1192  v.writeClassName(os);
1193  v.outAsciiNoName(os);
1194  return os;
1195  }
1196 
1197  /// @{
1198  /// Methods to serialize to a JSON stream. The matrix is stored as an
1199  /// array of 9 reals.
1200  bool save(UT_JSONWriter &w) const;
1201  bool save(UT_JSONValue &v) const;
1202  bool load(UT_JSONParser &p);
1203  /// @}
1204 
1205  /// Returns the vector size
1206  static int entries() { return tuple_size; }
1207 
1208  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
1209  /// order given by a templated UT_XformOrder.
1210  /// @{
1211  template <int ORDER>
1212  void rotate(T rx, T ry, T rz);
1213 
1214  /// If angle_degrees is an exact multiple of 90, it is changed to 0,
1215  /// and the quarter turn number (0-3) is returned. If angle_degrees
1216  /// is *not* an exact multiple of 90, it is left unchanged,
1217  /// and 0 is returned.
1218  static uint reduceExactQuarterTurns(T &angle_degrees);
1219 private:
1220  // Check this matrix to see if it is a valid rotation matrix, and permute
1221  // its elements depending on the rotOrder value in crack(). checkRot()
1222  // returns 0 if OK and 1 otherwise.
1223  int checkRot() const;
1224  void permute(int l0, int l1, int l2);
1225 
1226  // Operation to aid in cofactor computation
1228  void coVals(int k, int r[2]) const
1229  {
1230  switch(k)
1231  {
1232  case 0: r[0] = 1; r[1] = 2; break;
1233  case 1: r[0] = 0; r[1] = 2; break;
1234  case 2: r[0] = 0; r[1] = 1; break;
1235  }
1236  }
1237 
1238 
1239  void writeClassName(std::ostream &os) const;
1240  static const char *className();
1241 
1242  // The matrix data:
1243  union {
1244  T matx[3][3];
1245  T myFloats[tuple_size];
1246  };
1247 };
1248 
1249 #include "UT_Vector3.h"
1250 
1251 template <typename T>
1252 template <typename S>
1253 inline
1255 {
1256  matx[0][0] = matx[0][1] = matx[0][2] = vec.x();
1257  matx[1][0] = matx[1][1] = matx[1][2] = vec.y();
1258  matx[2][0] = matx[2][1] = matx[2][2] = vec.z();
1259  return *this;
1260 }
1261 
1262 template <typename T>
1263 template <typename S>
1264 inline
1266 {
1267  T x = vec.x(); T y = vec.y(); T z = vec.z();
1268  matx[0][0]+=x; matx[0][1]+=x; matx[0][2]+=x;
1269  matx[1][0]+=y; matx[1][1]+=y; matx[1][2]+=y;
1270  matx[2][0]+=z; matx[2][1]+=z; matx[2][2]+=z;
1271  return *this;
1272 }
1273 
1274 template <typename T>
1275 template <typename S>
1276 inline
1278 {
1279  T x = vec.x(); T y = vec.y(); T z = vec.z();
1280  matx[0][0]-=x; matx[0][1]-=x; matx[0][2]-=x;
1281  matx[1][0]-=y; matx[1][1]-=y; matx[1][2]-=y;
1282  matx[2][0]-=z; matx[2][1]-=z; matx[2][2]-=z;
1283  return *this;
1284 }
1285 
1286 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1287 template <> inline UT_Matrix3T<float>&
1289 {
1290  v4uf r0(m.matx[0]);
1291  v4uf r1(m.matx[1]);
1292  v4uf r2(m(2,0), m(2,1), m(2,2), 0.f);
1293 
1294  // Do not alter the order in which the rows are computed.
1295  // This routine relies on overriding
1296  const float m10 = matx[1][0];
1297  const float m20 = matx[2][0];
1298  {
1299  const v4uf row =
1300  r0 * v4uf(matx[0][0])
1301  + r1 * v4uf(matx[0][1])
1302  + r2 * v4uf(matx[0][2]);
1303  vm_store(matx[0], row.vector);
1304  }
1305  {
1306  const v4uf row =
1307  r0 * v4uf(m10)
1308  + r1 * v4uf(matx[1][1])
1309  + r2 * v4uf(matx[1][2]);
1310  vm_store(matx[1], row.vector);
1311  }
1312  {
1313  const v4uf row =
1314  r0 * v4uf(m20)
1315  + r1 * v4uf(matx[2][1])
1316  + r2 * v4uf(matx[2][2]);
1317 
1318  matx[2][0] = row[0];
1319  matx[2][1] = row[1];
1320  matx[2][2] = row[2];
1321  }
1322  return *this;
1323 }
1324 template <> template <> inline UT_Matrix3T<float>&
1326 {
1327  const auto& l = m.lowerTri();
1328 
1329  v4uf r0(l.q00, l.q10, l.q20, 0.f);
1330  v4uf r1(l.q10, l.q11, l.q21, 0.f);
1331  v4uf r2(l.q20, l.q21, l.q22, 0.f);
1332 
1333  // Do not alter the order in which the rows are computed.
1334  // This routine relies on overriding
1335  const float m10 = matx[1][0];
1336  const float m20 = matx[2][0];
1337  {
1338  const v4uf row =
1339  r0 * v4uf(matx[0][0])
1340  + r1 * v4uf(matx[0][1])
1341  + r2 * v4uf(matx[0][2]);
1342  vm_store(matx[0], row.vector);
1343  }
1344  {
1345  const v4uf row =
1346  r0 * v4uf(m10)
1347  + r1 * v4uf(matx[1][1])
1348  + r2 * v4uf(matx[1][2]);
1349  vm_store(matx[1], row.vector);
1350  }
1351  {
1352  const v4uf row =
1353  r0 * v4uf(m20)
1354  + r1 * v4uf(matx[2][1])
1355  + r2 * v4uf(matx[2][2]);
1356 
1357  matx[2][0] = row[0];
1358  matx[2][1] = row[1];
1359  matx[2][2] = row[2];
1360  }
1361  return *this;
1362 }
1363 #endif
1364 
1365 // Scaled outer product update (given scalar b, row vectors v1 and v2)
1366 // this += b * transpose(v1) * v2
1367 template <typename T>
1368 template <typename S>
1369 inline
1371  const UT_Vector3T<S> &v1,
1372  const UT_Vector3T<S> &v2)
1373 {
1374  T bv1;
1375  bv1 = b * v1.x();
1376  matx[0][0]+=bv1*v2.x();
1377  matx[0][1]+=bv1*v2.y();
1378  matx[0][2]+=bv1*v2.z();
1379  bv1 = b * v1.y();
1380  matx[1][0]+=bv1*v2.x();
1381  matx[1][1]+=bv1*v2.y();
1382  matx[1][2]+=bv1*v2.z();
1383  bv1 = b * v1.z();
1384  matx[2][0]+=bv1*v2.x();
1385  matx[2][1]+=bv1*v2.y();
1386  matx[2][2]+=bv1*v2.z();
1387 }
1388 
1389 template <typename T>
1390 inline
1392 {
1393  UT_ASSERT_P(row < 3);
1394  return *(const UT_Vector3T<T>*)(matx[row]);
1395 }
1396 
1397 template <typename T>
1398 inline
1400 {
1401  UT_ASSERT_P(row < 3);
1402  return *(UT_Vector3T<T>*)(matx[row]);
1403 }
1404 
1405 
1406 // Free floating functions:
1407 template <typename T, typename S>
1408 inline
1410 {
1411  return mat+vec;
1412 }
1413 
1414 template <typename T, typename S>
1415 inline
1417 {
1418  return m1*sc;
1419 }
1420 
1421 template <typename T, typename S>
1422 inline
1424 {
1425  return (m1 * (1.0f/scalar));
1426 }
1427 
1428 /// Multiplication of a row or column vector by a matrix (ie. right vs. left
1429 /// multiplication respectively). The operator*() declared above is an alias
1430 /// for rowVecMult(). The functions that take a 4x4 matrix first extend
1431 /// the vector to 4D (with a trailing 1.0 element).
1432 //
1433 // @{
1434 // Notes on optimisation of matrix/vector multiplies:
1435 // - multiply(dest, mat) functions have been deprecated in favour of
1436 // rowVecMult/colVecMult routines, which produce temporaries. For these to
1437 // offer comparable performance, the compiler has to optimize away the
1438 // temporary, but most modern compilers can do this. Performance tests with
1439 // gcc3.3 indicate that this is a realistic expectation for modern
1440 // compilers.
1441 // - since matrix/vector multiplies cannot be done without temporary data,
1442 // the "primary" functions are the global matrix/vector
1443 // rowVecMult/colVecMult routines, rather than the member functions.
1444 // - inlining is explicitly requested only for non-deprecated functions
1445 // involving the native types (UT_Vector3 and UT_Matrix3)
1446 
1447 template <typename T, typename S>
1448 inline UT_Vector3T<T> rowVecMult(const UT_Vector3T<T> &v, const UT_Matrix3T<S> &m);
1449 template <typename T, typename S>
1450 inline UT_Vector3T<T> colVecMult(const UT_Matrix3T<S> &m, const UT_Vector3T<T> &v);
1451 // @}
1452 
1453 template <typename T, typename S>
1454 inline
1456 {
1457  return UT_Vector3T<T>(
1458  v.x()*m(0,0) + v.y()*m(1,0) + v.z()*m(2,0),
1459  v.x()*m(0,1) + v.y()*m(1,1) + v.z()*m(2,1),
1460  v.x()*m(0,2) + v.y()*m(1,2) + v.z()*m(2,2)
1461  );
1462 }
1463 
1464 template <typename T, typename S>
1465 inline
1467 {
1468  return rowVecMult(v, m);
1469 }
1470 
1471 template <typename T, typename S>
1472 inline
1474 {
1475  return UT_Vector3T<T>(
1476  v.x()*m(0,0) + v.y()*m(0,1) + v.z()*m(0,2),
1477  v.x()*m(1,0) + v.y()*m(1,1) + v.z()*m(1,2),
1478  v.x()*m(2,0) + v.y()*m(2,1) + v.z()*m(2,2)
1479  );
1480 }
1481 
1482 template <typename T>
1483 SYS_FORCE_INLINE void
1485 {
1486  operator=(::rowVecMult(*this, m));
1487 }
1488 template <typename T>
1489 SYS_FORCE_INLINE void
1491 {
1492  operator=(::rowVecMult(*this, m));
1493 }
1494 template <typename T>
1495 SYS_FORCE_INLINE void
1497 {
1498  operator=(::colVecMult(m, *this));
1499 }
1500 template <typename T>
1501 SYS_FORCE_INLINE void
1503 {
1504  operator=(::colVecMult(m, *this));
1505 }
1506 template <typename T>
1507 template <typename S>
1510 {
1511  rowVecMult(m);
1512  return *this;
1513 }
1514 template <typename T>
1515 template <typename S>
1516 SYS_FORCE_INLINE void
1518 {
1519  colVecMult(mat);
1520 }
1521 template <typename T>
1522 template <typename S>
1523 SYS_FORCE_INLINE void
1525 {
1526  dest = ::colVecMult(mat, *this);
1527 }
1528 template <typename T>
1529 template <typename S>
1530 SYS_FORCE_INLINE void
1532 {
1533  dest = ::rowVecMult(*this, mat);
1534 }
1535 
1536 template <typename T>
1537 inline
1539 {
1540  return UT_Matrix3T<T>(
1541  SYSmin(v1(0,0), v2(0,0)),
1542  SYSmin(v1(0,1), v2(0,1)),
1543  SYSmin(v1(0,2), v2(0,2)),
1544  SYSmin(v1(1,0), v2(1,0)),
1545  SYSmin(v1(1,1), v2(1,1)),
1546  SYSmin(v1(1,2), v2(1,2)),
1547  SYSmin(v1(2,0), v2(2,0)),
1548  SYSmin(v1(2,1), v2(2,1)),
1549  SYSmin(v1(2,2), v2(2,2))
1550  );
1551 }
1552 
1553 template <typename T>
1554 inline
1556 {
1557  return UT_Matrix3T<T>(
1558  SYSmax(v1(0,0), v2(0,0)),
1559  SYSmax(v1(0,1), v2(0,1)),
1560  SYSmax(v1(0,2), v2(0,2)),
1561  SYSmax(v1(1,0), v2(1,0)),
1562  SYSmax(v1(1,1), v2(1,1)),
1563  SYSmax(v1(1,2), v2(1,2)),
1564  SYSmax(v1(2,0), v2(2,0)),
1565  SYSmax(v1(2,1), v2(2,1)),
1566  SYSmax(v1(2,2), v2(2,2))
1567  );
1568 }
1569 
1570 template <typename T,typename S>
1571 inline
1573 {
1574  return UT_Matrix3T<T>(
1575  SYSlerp(v1(0,0), v2(0,0), t),
1576  SYSlerp(v1(0,1), v2(0,1), t),
1577  SYSlerp(v1(0,2), v2(0,2), t),
1578  SYSlerp(v1(1,0), v2(1,0), t),
1579  SYSlerp(v1(1,1), v2(1,1), t),
1580  SYSlerp(v1(1,2), v2(1,2), t),
1581  SYSlerp(v1(2,0), v2(2,0), t),
1582  SYSlerp(v1(2,1), v2(2,1), t),
1583  SYSlerp(v1(2,2), v2(2,2), t)
1584  );
1585 }
1586 
1587 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1588 template <>
1589 inline
1591 {
1593  {
1594  const v4uf l(v1.data());
1595  const v4uf r(v2.data());
1596  vm_store(result.data(), SYSlerp(l, r, t).vector);
1597  }
1598  {
1599  const v4uf l(v1.data() + 4);
1600  const v4uf r(v2.data() + 4);
1601  vm_store(result.data() + 4, SYSlerp(l, r, t).vector);
1602  }
1603  {
1604  result(2,2) = SYSlerp(v1(2,2), v2(2,2), t);
1605  }
1606  return result;
1607 }
1608 #endif
1609 
1610 template<typename T>
1612 {
1614  typedef T DataType;
1615  static const exint TupleSize = 9;
1616  static const bool isVectorType = true;
1617 };
1618 
1619 // Overload for custom formatting of UT_Matrix3T<T> with UTformat.
1620 template<typename T>
1621 UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix3T<T> &v);
1622 
1623 
1624 template <typename T> template<int ORDER>
1625 void
1626 UT_Matrix3T<T>::rotate(T rx, T ry, T rz)
1627 {
1628  switch(ORDER)
1629  {
1630  case 0://UT_XformOrder::XYZ:
1631  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1632  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1633  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1634  break;
1635 
1636  case 1:
1637  //case UT_XformOrder::XZY:
1638  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1639  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1640  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1641  break;
1642 
1643  case 2:
1644  //case UT_XformOrder::YXZ:
1645  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1646  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1647  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1648  break;
1649 
1650  case 3:
1651  //case UT_XformOrder::YZX:
1652  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1653  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1654  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1655  break;
1656 
1657  case 4:
1658  //case UT_XformOrder::ZXY:
1659  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1660  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1661  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1662  break;
1663 
1664  case 5:
1665  //case UT_XformOrder::ZYX:
1666  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1667  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1668  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1669  break;
1670 
1671  default:
1672  break;
1673  }
1674 }
1675 
1676 #endif
static int entries()
Returns the vector size.
Definition: UT_Matrix3.h:1206
UT_Vector3T< T > rowVecMult(const UT_Vector3T< T > &v, const UT_Matrix3T< S > &m)
Definition: UT_Matrix3.h:1455
GLdouble s
Definition: glew.h:1390
SYS_FORCE_INLINE T & operator()(unsigned row, unsigned col) noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:1133
int isZero() const
Definition: UT_Matrix3.h:1110
UT_Matrix3T< T > & operator=(const UT_SymMatrix3T< S > &m)
Convert from a symmetric matrix to non-symmetric.
Definition: UT_Matrix3.h:198
Mat3< typename promote< S, T >::type > operator*(S scalar, const Mat3< T > &m)
Multiply each element of the given matrix by scalar and return the result.
Definition: Mat3.h:609
GLboolean invert
Definition: glew.h:1422
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:417
void leftMult(const UT_SymMatrix3T< S > &m)
Multiply given symmetric matrix on the left.
Definition: UT_Matrix3.h:340
#define SYS_STATIC_ASSERT(expr)
UT_Matrix3T< T > transposedCopy() const
Definition: UT_Matrix3.h:655
GLenum src
Definition: glew.h:2410
UT_SymMatrix3T< T > averagedSymMatrix3() const
Convert this to a symmetric matrix, using averaged components.
Definition: UT_Matrix3.h:225
#define SYS_DEPRECATED(__V__)
UT_SymMatrix3T< T > upperTriangularSymMatrix3() const
Convert this to a symmetric matrix, using the upper-triangular portion.
Definition: UT_Matrix3.h:217
void leftMult(const UT_Matrix3T< S > &m)
Multiply given matrix3 on the left.
Definition: UT_Matrix3.h:365
constexpr bool operator!=(const UT_Matrix3T< T > &m) const noexcept
Definition: UT_Matrix3.h:395
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:1153
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:720
constexpr bool operator==(const UT_Matrix3T< T > &m) const noexcept
Definition: UT_Matrix3.h:388
SYS_FORCE_INLINE void colVecMult(const UT_Matrix3F &m)
Definition: UT_Matrix3.h:1496
UT_Matrix3T< T > & operator*=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:291
GLuint const GLfloat * val
Definition: glew.h:2794
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Add corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:625
UT_Matrix3T(const UT_SymMatrix3T< S > m)
Construct from a symmetric 3x3 matrix.
Definition: UT_Matrix3.h:170
void extractScales(UT_Vector3F &scales, UT_Vector3F *shears=0)
Definition: UT_Matrix3.h:981
SYS_FORCE_INLINE T operator()(unsigned row, unsigned col) const noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:1139
GLenum GLenum GLenum GLenum GLenum scale
Definition: glew.h:13880
T determinant() const
Definition: UT_Matrix3.h:575
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:9477
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:1555
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:259
int isIdentity() const
Definition: UT_Matrix3.h:1098
JSON reader class which handles parsing of JSON or bJSON files.
Definition: UT_JSONParser.h:75
#define UT_API
Definition: UT_API.h:13
Generic symmetric 3x3 matrix.
Definition: UT_SymMatrix3.h:27
const GLdouble * m
Definition: glew.h:9124
T * operator()(unsigned row)
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix3.h:1148
GLdouble l
Definition: glew.h:9122
Class which writes ASCII or binary JSON streams.
Definition: UT_JSONWriter.h:32
const GLdouble * v
Definition: glew.h:1391
void extractScales(UT_Vector3T< fpreal16 > &scales, UT_Vector3T< fpreal16 > *shears=0)
Definition: UT_Matrix3.h:983
void prescale(T sx, T sy, T sz)
Definition: UT_Matrix3.h:862
static const exint TupleSize
SYS_FORCE_INLINE T & x(void)
Definition: UT_Vector3.h:507
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
T * data(void)
Return the raw matrix data.
Definition: UT_Matrix3.h:1125
UT_Matrix3T< T > SYSmin(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2)
Definition: UT_Matrix3.h:1538
2D Vector class.
Definition: UT_Vector2.h:145
GLuint GLdouble GLdouble GLint GLint order
Definition: glew.h:3446
SYS_FORCE_INLINE void pretranslate(const UT_Vector2T< T > &delta)
Definition: UT_Matrix3.h:906
GLdouble GLdouble z
Definition: glew.h:1559
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
SYS_FORCE_INLINE T & z(void)
Definition: UT_Vector3.h:511
GLdouble GLdouble GLdouble GLdouble q
Definition: glew.h:1414
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:438
SYS_FORCE_INLINE void shear(const UT_Vector3T< T > &sh)
Definition: UT_Matrix3.h:1029
GLfloat GLfloat GLfloat v2
Definition: glew.h:1856
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:1517
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:1094
GLclampf f
Definition: glew.h:3499
UT_Matrix3T< T > SYSlerp(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2, S t)
Definition: UT_Matrix3.h:1572
GLint GLint GLint GLint GLint x
Definition: glew.h:1252
GLint GLint GLint GLint GLint GLint y
Definition: glew.h:1252
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Subtract corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:635
OIIO_FORCEINLINE const vint4 & operator+=(vint4 &a, const vint4 &b)
Definition: simd.h:4246
int64 exint
Definition: SYS_Types.h:120
GLuint buffer
Definition: glew.h:1680
GLint GLenum GLsizei GLint GLsizei const void * data
Definition: glew.h:1379
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:134
const GLuint GLenum const void * binary
Definition: glew.h:3502
SYS_FORCE_INLINE void scale(const UT_Vector3T< T > &s)
Definition: UT_Matrix3.h:856
double fpreal64
Definition: SYS_Types.h:196
class UT_API UT_Matrix3T
fpreal64 dot(const CE_VectorT< T > &a, const CE_VectorT< T > &b)
Definition: CE_Vector.h:218
static const bool isVectorType
void outerproductUpdateT(T b, const UT_Vector3T< S > &v1, const UT_Vector3T< S > &v2)
Definition: UT_Matrix3.h:1370
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
GLubyte GLubyte GLubyte GLubyte w
Definition: glew.h:1890
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:1244
Definition: VM_SIMD.h:188
ImageBuf OIIO_API rotate(const ImageBuf &src, float angle, string_view filtername=string_view(), float filterwidth=0.0f, bool recompute_roi=false, ROI roi={}, int nthreads=0)
const GLfloat * c
Definition: glew.h:16296
SYS_FORCE_INLINE void rowVecMult(const UT_Matrix3F &m)
Definition: UT_Matrix3.h:1484
SYS_FORCE_INLINE void outerproductUpdate(T b, const UT_Vector3D &v1, const UT_Vector3D &v2)
Definition: UT_Matrix3.h:443
UT_Matrix3T< T > & operator=(const UT_Matrix3T< S > &m) noexcept
Definition: UT_Matrix3.h:188
constexpr UT_Matrix3T(fpreal64 val) noexcept
Construct identity matrix, multipled by scalar.
Definition: UT_Matrix3.h:109
bool INST SYS_FORCE_INLINE UT_Matrix3T(const UT_FixedVector< S, 3, INST > &r0, const UT_FixedVector< S, 3, INST > &r1, const UT_FixedVector< S, 3, INST > &r2) noexcept
Definition: UT_Matrix3.h:136
const Vec2< S > & operator*=(Vec2< S > &v, const Matrix33< T > &m)
Definition: ImathMatrix.h:3322
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
void translate(T dx, T dy)
Definition: UT_Matrix3.h:883
SYS_FORCE_INLINE UT_Vector3T< T > & operator*=(const UT_Matrix3T< S > &m)
Definition: UT_Matrix3.h:1509
GA_API const UT_StringHolder orient
unsigned int uint
Definition: SYS_Types.h:44
UT_SymMatrix3T< T > lowerTriangularSymMatrix3() const
Convert this to a symmetric matrix, using the lower-triangular portion.
Definition: UT_Matrix3.h:209
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:313
SYS_FORCE_INLINE void rotateHalf()
Definition: UT_Matrix3.h:744
UT_Matrix3T< T > operator-() const
Definition: UT_Matrix3.h:235
const UT_Vector3T< T > & operator[](unsigned row) const
Return a matrix row. No bounds checking on subscript.
Definition: UT_Matrix3.h:1391
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:832
void shear(T s_xy, T s_xz, T s_yz)
Definition: UT_Matrix3.h:1017
Inner class to access the elements symbolically.
IFDmantra py
Definition: HDK_Image.dox:266
GLdouble GLdouble GLdouble b
Definition: glew.h:9122
GLfloat GLfloat p
Definition: glew.h:16321
SYS_FORCE_INLINE T & y(void)
Definition: UT_Vector3.h:509
Quaternion class.
Definition: UT_Quaternion.h:51
const T * data(void) const
Return the raw matrix data.
Definition: UT_Matrix3.h:1124
GA_API const UT_StringHolder up
bool isSymmetric(const MatType &m)
Determine if a matrix is symmetric.
Definition: Mat.h:912
SYS_FORCE_INLINE UT_Matrix3T< T > & operator-=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:275
void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
Definition: UT_Matrix3.h:979
GLdouble GLdouble GLdouble r
Definition: glew.h:1406
UT_Vector3T< T > colVecMult(const UT_Matrix3T< S > &m, const UT_Vector3T< T > &v)
Definition: UT_Matrix3.h:1473
GA_API const UT_StringHolder pscale
unsigned hash() const
Compute a hash.
Definition: UT_Matrix3.h:1129
GLfloat v0
Definition: glew.h:1848
Class to store JSON objects as C++ objects.
Definition: UT_JSONValue.h:76
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:244
bool isAlmostEqual(const UT_Matrix3T< T > &m, int ulps=50) const
Definition: UT_Matrix3.h:679
T getEuclideanNorm() const
Definition: UT_Matrix3.h:1164
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4269
GLuint64EXT * result
Definition: glew.h:14007
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:207
void zero()
Set the matrix to zero.
Definition: UT_Matrix3.h:1096
void conditionRotate(UT_Vector3F *scales=0)
Definition: UT_Matrix3.h:966
void conditionRotate(UT_Vector3D *scales)
Definition: UT_Matrix3.h:968
#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
SYS_FORCE_INLINE void prerotateHalf()
Definition: UT_Matrix3.h:817
GLenum GLenum void * row
Definition: glew.h:4965
SYS_FORCE_INLINE void multiply(UT_Vector3T< T > &dest, const UT_Matrix4T< S > &mat) const
Definition: UT_Matrix4.h:1990
UT_Matrix3T< T > operator/(const UT_Matrix3T< T > &mat, S sc)
Definition: UT_Matrix3.h:1423
void transpose(void)
Definition: UT_Matrix3.h:648
SYS_FORCE_INLINE void rotateWithQTurns(T theta, uint qturns)
Definition: UT_Matrix3.h:759
void pretranslate(T dx, T dy)
Definition: UT_Matrix3.h:899
UT_FixedVector< T, 9 > FixedVectorType
Definition: UT_Matrix3.h:1613
T trace() const
Definition: UT_Matrix3.h:581
GLdouble GLdouble t
Definition: glew.h:1398
GLfloat GLfloat v1
Definition: glew.h:1852
v4sf vector
Definition: VM_SIMD.h:348
bool INST SYS_FORCE_INLINE UT_Matrix3T(const UT_FixedVector< S, tuple_size, INST > &v) noexcept
Definition: UT_Matrix3.h:127
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:409
bool isLowerTriangular(T tolerance=T(SYS_FTOLERANCE)) const
Check for lower triangular within a tolerance level to 0.
Definition: UT_Matrix3.h:698