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()
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  /// Perform the polar decomposition M into an orthogonal matrix Q and an
924  /// symmetric positive-semidefinite matrix S. This is more useful than
925  /// crack() or conditionRotate() when the desire is to blend transforms.
926  /// By default, it gives M=SQ, a left polar decomposition. If reverse is
927  /// false, then it gives M=QS, a right polar decomposition.
928  /// @pre *this is non-singular
929  /// @post *this = Q, and if stretch != 0: *stretch = S
930  /// @return True if successful
931  bool polarDecompose(
932  UT_Matrix3T<T> *stretch = nullptr,
933  bool reverse = true,
934  const int max_iter = 64,
935  const T rel_tol = FLT_EPSILON);
936 
937  /// Turn this matrix into the "closest" rotation matrix.
938  ///
939  /// It uses polarDecompose and then negates the matrix and stretch
940  /// if there is a negative determinant (scale). It returns false iff
941  /// polarDecompose failed, possibly due to a singular matrix.
942  ///
943  /// This is currently the one true way to turn an arbitrary
944  /// matrix into a rotation matrix. If that ever changes,
945  /// put a warning here, and you may want to update
946  /// UT_Matrix4::makeRigidMatrix too.
947  bool makeRotationMatrix(
948  UT_Matrix3T<T> *stretch = nullptr,
949  bool reverse = true,
950  const int max_iter = 64,
951  const T rel_tol = FLT_EPSILON);
952 
953  /// This method will condition the matrix so that it's a valid rotation
954  /// matrix (i.e. crackable). Ideally, the scales should be removed first,
955  /// but this method will attempt to do this as well. It will return the
956  /// conditioned scales if a vector is passed in.
957  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
958  /// @{
959  template <typename S>
960  void conditionRotateT(UT_Vector3T<S> *scales);
961  void conditionRotate(UT_Vector3F *scales=0)
962  { conditionRotateT(scales); }
964  { conditionRotateT(scales); }
965  /// @}
966 
967  /// Extract scales and shears leaving this as an orthogonal rotation matrix
968  /// using the transform order Scales * Shears * Rotate.
969  /// @note The shears are in the order [XY, XZ, YZ]
970  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
971  /// @{
972  template <typename S>
973  void extractScalesT(UT_Vector3T<S> &scales, UT_Vector3T<S> *shears);
974  void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
975  { extractScalesT(scales, shears); }
976  void extractScales(UT_Vector3F &scales, UT_Vector3F *shears=0)
977  { extractScalesT(scales, shears); }
979  UT_Vector3T<fpreal16> *shears=0)
980  { extractScalesT(scales, shears); }
981  /// @}
982 
983  /// Extract scales and shears leaving this as an orthogonal rotation matrix
984  /// (assuming it was only a 2D xform to begin with) using the transform
985  /// order Rotate * Scales * Shears. The shears are XY.
986  template <typename S>
987  void extractScales2D(UT_Vector2T<S> &scales, S *shears=0);
988 
989  /// Extract scales and shears leaving this as an orthogonal rotation matrix
990  /// using the transform order Rotate * Scales * Shears.
991  /// @note The shears are in the order [XY, XZ, YZ]
992  /// WARNING: If you just want a rotation matrix, use makeRotationMatrix()!
993  template <typename S>
994  void rightExtractScales(UT_Vector3T<S> &scales,
995  UT_Vector3T<S> *shears = nullptr);
996 
997  /// Extract scales and shears leaving this as an orthogonal rotation matrix
998  /// (assuming it was only a 2D xform to begin with) using the transform
999  /// order Scales * Shears * Rotate. The shears are XY.
1000  template <typename S>
1001  void rightExtractScales2D(UT_Vector2T<S> &scales,
1002  S *shears = nullptr);
1003 
1004  // Shear the matrix according to the values. This is equivalent to
1005  // multiplying the matrix by the shear matrix with the given value.
1006  void shearXY(T val);
1007  void shearXZ(T val);
1008  void shearYZ(T val);
1009 
1010  /// Post-multiply this matrix by the shear matrix formed by (sxy, sxz, syz)
1011  /// @{
1012  void shear(T s_xy, T s_xz, T s_yz)
1013  {
1014  matx[0][0] += matx[0][1]*s_xy + matx[0][2]*s_xz;
1015  matx[0][1] += matx[0][2]*s_yz;
1016 
1017  matx[1][0] += matx[1][1]*s_xy + matx[1][2]*s_xz;
1018  matx[1][1] += matx[1][2]*s_yz;
1019 
1020  matx[2][0] += matx[2][1]*s_xy + matx[2][2]*s_xz;
1021  matx[2][1] += matx[2][2]*s_yz;
1022  }
1024  void shear(const UT_Vector3T<T> &sh)
1025  { shear(sh(0), sh(1), sh(2)); }
1026  /// @}
1027 
1028  // Solve a 3x3 system of equations A*x=b, where A is this matrix,
1029  // b or (cx, cy, cz) is given and x is unknown. The method returns 0 if the
1030  // determinant is not 0, and 1 otherwise.
1031  template <typename S>
1032  int solve(T cx, T cy, T cz,
1033  UT_Vector3T<S> &result) const;
1034  template <typename S>
1035  int solve(const UT_Vector3T<S> &b,
1036  UT_Vector3T<S> &result) const;
1037 
1038  // Solve a 3x3 system of equations x*A=b, where A is this matrix,
1039  // b or (cx, cy, cz) is given and x is unknown. The method returns 0 if the
1040  // determinant is not 0, and 1 otherwise.
1041  template <typename S>
1042  int solveTranspose(T cx, T cy, T cz,
1043  UT_Vector3T<S> &result) const;
1044  template <typename S>
1045  int solveTranspose(const UT_Vector3T<S> &b,
1046  UT_Vector3T<S> &result) const;
1047 
1048  // Space change operation: right multiply this matrix by the 3x3 matrix
1049  // of the transformation which moves the vector space defined by
1050  // (iSrc, jSrc, cross(iSrc,jSrc)) into the space defined by
1051  // (iDest, jDest, cross(iDest,jDest)). iSrc, jSrc, iDest, and jDest will
1052  // be normalized before the operation if norm is 1. This matrix transforms
1053  // iSrc into iDest, and jSrc into jDest.
1054  template <typename S>
1055  void changeSpace(UT_Vector3T<S> &iSrc, UT_Vector3T<S> &jSrc,
1056  UT_Vector3T<S> &iDest,UT_Vector3T<S> &jDest,
1057  int norm=1);
1058 
1059  // Multiply this matrix by the general transform matrix built from
1060  // translations (tx,ty), degree rotation (rz), scales (sx,sy),
1061  // and possibly a pivot point (px,py). The second methos leaves us
1062  // unchanged, and returns a new (this*xform) instead. The order of the
1063  // multiplies (SRT, RST, Rz, etc) is stored in 'order'. Normally you
1064  // will ignore the 'reverse' parameter, which tells us to build the
1065  // matrix from last to first xform, and to apply some inverses to
1066  // txy, rz, and sxy.
1067  void xform(const UT_XformOrder &order,
1068  T tx=0.0f, T ty=0.0f, T rz=0.0f,
1069  T sx=1.0f, T sy=1.0f,T px=0.0f,T py=0.0f,
1070  int reverse=0);
1071 
1072  // this version handles shears as well
1073  void xform(const UT_XformOrder &order,
1074  T tx, T ty, T rz,
1075  T sx, T sy, T s_xy,
1076  T px, T py,
1077  int reverse=0);
1078 
1079  // Right multiply this matrix by a 3x3 matrix which scales by a given
1080  // amount along the direction of vector v. When applied to a vector w,
1081  // the stretched matrix (*this) stretches w in v by the amount given.
1082  // If norm is non-zero, v will be normalized prior to the operation.
1083  template <typename S>
1084  void stretch(UT_Vector3T<S> &v, T amount, int norm=1);
1085  template <typename S>
1086  SYS_DEPRECATED(12.0) UT_Matrix3T<T> stretch(UT_Vector3T<S> &v, T amount, int norm=1) const;
1087 
1088  //
1089  // This does a test to see if a vector transformed by the matrix
1090  // will maintain it's length (i.e. there are no scales in the matrix)
1091  int isNormalized() const;
1092 
1093  // Return the dot product between two rows i and j:
1094  T dot(unsigned i, unsigned j) const
1095  {
1096  return (i <= 2 && j <= 2) ?
1097  matx[i][0]*matx[j][0] + matx[i][1]*matx[j][1] +
1098  matx[i][2]*matx[j][2] : (T)0;
1099  }
1100 
1101  /// Set the matrix to identity
1102  void identity() { *this = 1; }
1103  /// Set the matrix to zero
1104  void zero() { *this = 0; }
1105 
1106  int isIdentity() const
1107  {
1108  // NB: DO NOT USE TOLERANCES
1109  return(
1110  matx[0][0]==1.0f && matx[0][1]==0.0f &&
1111  matx[0][2]==0.0f && matx[1][0]==0.0f &&
1112  matx[1][1]==1.0f && matx[1][2]==0.0f &&
1113  matx[2][0]==0.0f && matx[2][1]==0.0f &&
1114  matx[2][2]==1.0f
1115  );
1116  }
1117 
1118  int isZero() const
1119  {
1120  // NB: DO NOT USE TOLERANCES
1121  return (
1122  matx[0][0]==0.0f && matx[0][1]==0.0f &&
1123  matx[0][2]==0.0f && matx[1][0]==0.0f &&
1124  matx[1][1]==0.0f && matx[1][2]==0.0f &&
1125  matx[2][0]==0.0f && matx[2][1]==0.0f &&
1126  matx[2][2]==0.0f
1127  );
1128  }
1129 
1130  /// Return the raw matrix data.
1131  // @{
1132  const T *data() const { return myFloats; }
1133  T *data() { return myFloats; }
1134  // @}
1135 
1136  /// Compute a hash
1137  unsigned hash() const { return SYSvector_hash(data(), tuple_size); }
1138 
1139  /// Return a matrix entry. No bounds checking on subscripts.
1140  // @{
1141  SYS_FORCE_INLINE T &operator()(unsigned row, unsigned col) noexcept
1142  {
1143  UT_ASSERT_P(row < 3 && col < 3);
1144  return matx[row][col];
1145  }
1147  T operator()(unsigned row, unsigned col) const noexcept
1148  {
1149  UT_ASSERT_P(row < 3 && col < 3);
1150  return matx[row][col];
1151  }
1152  // @}
1153 
1154  /// Return a matrix row. No bounds checking on subscript.
1155  // @{
1156  T *operator()(unsigned row)
1157  {
1158  UT_ASSERT_P(row < 3);
1159  return matx[row];
1160  }
1161  const T *operator()(unsigned row) const
1162  {
1163  UT_ASSERT_P(row < 3);
1164  return matx[row];
1165  }
1166  inline const UT_Vector3T<T> &operator[](unsigned row) const;
1167  inline UT_Vector3T<T> &operator[](unsigned row);
1168  // @}
1169 
1170  /// Dot product with another matrix
1171  /// Does dot(a,b) = sum_ij a_ij * b_ij
1172  T dot(const UT_Matrix3T<T> &m) const;
1173 
1174  /// Euclidean or Frobenius norm of a matrix.
1175  /// Does sqrt(sum(a_ij ^2))
1177  { return SYSsqrt(getEuclideanNorm2()); }
1178  /// Euclidean norm squared.
1179  T getEuclideanNorm2() const;
1180 
1181  /// Get the squared Euclidean distance between '*this' and 'from'
1182  /// Returns sum_ij(sqr(b_ij-a_ij))
1183  T distanceSquared(const UT_Matrix3T<T> &src);
1184 
1185  /// Get the 1-norm of this matrix, assuming a row vector convention.
1186  /// Returns the maximum absolute row sum. ie. max_i(sum_j(abs(a_ij)))
1187  T getNorm1() const;
1188 
1189  /// Get the inf-norm of this matrix, assuming a row vector convention.
1190  /// Returns the maximum absolute column sum. ie. max_j(sum_i(abs(a_ij)))
1191  T getNormInf() const;
1192 
1193  /// Get the max-norm of this matrix
1194  /// Returns the maximum absolute entry. ie. max_j(max_i(abs(a_ij)))
1195  T getNormMax() const;
1196 
1197  // I/O methods. Return 0 if read/write successful, -1 if unsuccessful.
1198  int save(std::ostream &os, int binary) const;
1199  bool load(UT_IStream &is);
1200 
1201  void outAsciiNoName(std::ostream &os) const;
1202 
1203  static const UT_Matrix3T<T> &getIdentityMatrix();
1204 
1205  // I/O friends:
1206  friend std::ostream &operator<<(std::ostream &os, const UT_Matrix3T<T> &v)
1207  {
1208  v.writeClassName(os);
1209  v.outAsciiNoName(os);
1210  return os;
1211  }
1212 
1213  /// @{
1214  /// Methods to serialize to a JSON stream. The matrix is stored as an
1215  /// array of 9 reals.
1216  bool save(UT_JSONWriter &w) const;
1217  bool save(UT_JSONValue &v) const;
1218  bool load(UT_JSONParser &p);
1219  /// @}
1220 
1221  /// Returns the vector size
1222  static int entries() { return tuple_size; }
1223 
1224  /// Post-rotate by rx, ry, rz radians around the three basic axes in the
1225  /// order given by a templated UT_XformOrder.
1226  /// @{
1227  template <int ORDER>
1228  void rotate(T rx, T ry, T rz);
1229 
1230  /// If angle_degrees is an exact multiple of 90, it is changed to 0,
1231  /// and the quarter turn number (0-3) is returned. If angle_degrees
1232  /// is *not* an exact multiple of 90, it is left unchanged,
1233  /// and 0 is returned.
1234  static uint reduceExactQuarterTurns(T &angle_degrees);
1235 private:
1236  // Check this matrix to see if it is a valid rotation matrix, and permute
1237  // its elements depending on the rotOrder value in crack(). checkRot()
1238  // returns 0 if OK and 1 otherwise.
1239  int checkRot() const;
1240 
1241  // Operation to aid in cofactor computation
1243  void coVals(int k, int r[2]) const
1244  {
1245  switch(k)
1246  {
1247  case 0: r[0] = 1; r[1] = 2; break;
1248  case 1: r[0] = 0; r[1] = 2; break;
1249  case 2: r[0] = 0; r[1] = 1; break;
1250  }
1251  }
1252 
1253 
1254  void writeClassName(std::ostream &os) const;
1255  static const char *className();
1256 
1257  inline T distanceSquaredInline(const UT_Matrix3T<T> &m);
1258 
1259  // The matrix data:
1260  union {
1261  T matx[3][3];
1262  T myFloats[tuple_size];
1263  };
1264 
1265  // To allow calling private methods from polarDecompose since it forces
1266  // fpreal64 precision.
1267  friend UT_Matrix3T<fpreal32>;
1268  friend UT_Matrix3T<fpreal64>;
1269 };
1270 
1271 #include "UT_Vector3.h"
1272 
1273 template <typename T>
1274 template <typename S>
1275 inline
1277 {
1278  matx[0][0] = matx[0][1] = matx[0][2] = vec.x();
1279  matx[1][0] = matx[1][1] = matx[1][2] = vec.y();
1280  matx[2][0] = matx[2][1] = matx[2][2] = vec.z();
1281  return *this;
1282 }
1283 
1284 template <typename T>
1285 template <typename S>
1286 inline
1288 {
1289  T x = vec.x(); T y = vec.y(); T z = vec.z();
1290  matx[0][0]+=x; matx[0][1]+=x; matx[0][2]+=x;
1291  matx[1][0]+=y; matx[1][1]+=y; matx[1][2]+=y;
1292  matx[2][0]+=z; matx[2][1]+=z; matx[2][2]+=z;
1293  return *this;
1294 }
1295 
1296 template <typename T>
1297 template <typename S>
1298 inline
1300 {
1301  T x = vec.x(); T y = vec.y(); T z = vec.z();
1302  matx[0][0]-=x; matx[0][1]-=x; matx[0][2]-=x;
1303  matx[1][0]-=y; matx[1][1]-=y; matx[1][2]-=y;
1304  matx[2][0]-=z; matx[2][1]-=z; matx[2][2]-=z;
1305  return *this;
1306 }
1307 
1308 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1309 template <> inline UT_Matrix3T<float>&
1311 {
1312  v4uf r0(m.matx[0]);
1313  v4uf r1(m.matx[1]);
1314  v4uf r2(m(2,0), m(2,1), m(2,2), 0.f);
1315 
1316  // Do not alter the order in which the rows are computed.
1317  // This routine relies on overriding
1318  const float m10 = matx[1][0];
1319  const float m20 = matx[2][0];
1320  {
1321  const v4uf row =
1322  r0 * v4uf(matx[0][0])
1323  + r1 * v4uf(matx[0][1])
1324  + r2 * v4uf(matx[0][2]);
1325  vm_store(matx[0], row.vector);
1326  }
1327  {
1328  const v4uf row =
1329  r0 * v4uf(m10)
1330  + r1 * v4uf(matx[1][1])
1331  + r2 * v4uf(matx[1][2]);
1332  vm_store(matx[1], row.vector);
1333  }
1334  {
1335  const v4uf row =
1336  r0 * v4uf(m20)
1337  + r1 * v4uf(matx[2][1])
1338  + r2 * v4uf(matx[2][2]);
1339 
1340  matx[2][0] = row[0];
1341  matx[2][1] = row[1];
1342  matx[2][2] = row[2];
1343  }
1344  return *this;
1345 }
1346 template <> template <> inline UT_Matrix3T<float>&
1348 {
1349  const auto& l = m.lowerTri();
1350 
1351  v4uf r0(l.q00, l.q10, l.q20, 0.f);
1352  v4uf r1(l.q10, l.q11, l.q21, 0.f);
1353  v4uf r2(l.q20, l.q21, l.q22, 0.f);
1354 
1355  // Do not alter the order in which the rows are computed.
1356  // This routine relies on overriding
1357  const float m10 = matx[1][0];
1358  const float m20 = matx[2][0];
1359  {
1360  const v4uf row =
1361  r0 * v4uf(matx[0][0])
1362  + r1 * v4uf(matx[0][1])
1363  + r2 * v4uf(matx[0][2]);
1364  vm_store(matx[0], row.vector);
1365  }
1366  {
1367  const v4uf row =
1368  r0 * v4uf(m10)
1369  + r1 * v4uf(matx[1][1])
1370  + r2 * v4uf(matx[1][2]);
1371  vm_store(matx[1], row.vector);
1372  }
1373  {
1374  const v4uf row =
1375  r0 * v4uf(m20)
1376  + r1 * v4uf(matx[2][1])
1377  + r2 * v4uf(matx[2][2]);
1378 
1379  matx[2][0] = row[0];
1380  matx[2][1] = row[1];
1381  matx[2][2] = row[2];
1382  }
1383  return *this;
1384 }
1385 #endif
1386 
1387 // Scaled outer product update (given scalar b, row vectors v1 and v2)
1388 // this += b * transpose(v1) * v2
1389 template <typename T>
1390 template <typename S>
1391 inline
1393  const UT_Vector3T<S> &v1,
1394  const UT_Vector3T<S> &v2)
1395 {
1396  T bv1;
1397  bv1 = b * v1.x();
1398  matx[0][0]+=bv1*v2.x();
1399  matx[0][1]+=bv1*v2.y();
1400  matx[0][2]+=bv1*v2.z();
1401  bv1 = b * v1.y();
1402  matx[1][0]+=bv1*v2.x();
1403  matx[1][1]+=bv1*v2.y();
1404  matx[1][2]+=bv1*v2.z();
1405  bv1 = b * v1.z();
1406  matx[2][0]+=bv1*v2.x();
1407  matx[2][1]+=bv1*v2.y();
1408  matx[2][2]+=bv1*v2.z();
1409 }
1410 
1411 template <typename T>
1412 inline
1414 {
1415  UT_ASSERT_P(row < 3);
1416  return *(const UT_Vector3T<T>*)(matx[row]);
1417 }
1418 
1419 template <typename T>
1420 inline
1422 {
1423  UT_ASSERT_P(row < 3);
1424  return *(UT_Vector3T<T>*)(matx[row]);
1425 }
1426 
1427 
1428 // Free floating functions:
1429 template <typename T, typename S>
1430 inline
1432 {
1433  return mat+vec;
1434 }
1435 
1436 template <typename T, typename S>
1437 inline
1439 {
1440  return m1*sc;
1441 }
1442 
1443 template <typename T, typename S>
1444 inline
1446 {
1447  return (m1 * (1.0f/scalar));
1448 }
1449 
1450 /// Multiplication of a row or column vector by a matrix (ie. right vs. left
1451 /// multiplication respectively). The operator*() declared above is an alias
1452 /// for rowVecMult(). The functions that take a 4x4 matrix first extend
1453 /// the vector to 4D (with a trailing 1.0 element).
1454 //
1455 // @{
1456 // Notes on optimisation of matrix/vector multiplies:
1457 // - multiply(dest, mat) functions have been deprecated in favour of
1458 // rowVecMult/colVecMult routines, which produce temporaries. For these to
1459 // offer comparable performance, the compiler has to optimize away the
1460 // temporary, but most modern compilers can do this. Performance tests with
1461 // gcc3.3 indicate that this is a realistic expectation for modern
1462 // compilers.
1463 // - since matrix/vector multiplies cannot be done without temporary data,
1464 // the "primary" functions are the global matrix/vector
1465 // rowVecMult/colVecMult routines, rather than the member functions.
1466 // - inlining is explicitly requested only for non-deprecated functions
1467 // involving the native types (UT_Vector3 and UT_Matrix3)
1468 
1469 template <typename T, typename S>
1470 inline UT_Vector3T<T> rowVecMult(const UT_Vector3T<T> &v, const UT_Matrix3T<S> &m);
1471 template <typename T, typename S>
1472 inline UT_Vector3T<T> colVecMult(const UT_Matrix3T<S> &m, const UT_Vector3T<T> &v);
1473 // @}
1474 
1475 template <typename T, typename S>
1476 inline
1478 {
1479  return UT_Vector3T<T>(
1480  v.x()*m(0,0) + v.y()*m(1,0) + v.z()*m(2,0),
1481  v.x()*m(0,1) + v.y()*m(1,1) + v.z()*m(2,1),
1482  v.x()*m(0,2) + v.y()*m(1,2) + v.z()*m(2,2)
1483  );
1484 }
1485 
1486 template <typename T, typename S>
1487 inline
1489 {
1490  return rowVecMult(v, m);
1491 }
1492 
1493 template <typename T, typename S>
1494 inline
1496 {
1497  return UT_Vector3T<T>(
1498  v.x()*m(0,0) + v.y()*m(0,1) + v.z()*m(0,2),
1499  v.x()*m(1,0) + v.y()*m(1,1) + v.z()*m(1,2),
1500  v.x()*m(2,0) + v.y()*m(2,1) + v.z()*m(2,2)
1501  );
1502 }
1503 
1504 template <typename T>
1505 SYS_FORCE_INLINE void
1507 {
1508  operator=(::rowVecMult(*this, m));
1509 }
1510 template <typename T>
1511 SYS_FORCE_INLINE void
1513 {
1514  operator=(::rowVecMult(*this, m));
1515 }
1516 template <typename T>
1517 SYS_FORCE_INLINE void
1519 {
1520  operator=(::colVecMult(m, *this));
1521 }
1522 template <typename T>
1523 SYS_FORCE_INLINE void
1525 {
1526  operator=(::colVecMult(m, *this));
1527 }
1528 template <typename T>
1529 template <typename S>
1532 {
1533  rowVecMult(m);
1534  return *this;
1535 }
1536 template <typename T>
1537 template <typename S>
1538 SYS_FORCE_INLINE void
1540 {
1541  colVecMult(mat);
1542 }
1543 template <typename T>
1544 template <typename S>
1545 SYS_FORCE_INLINE void
1547 {
1548  dest = ::colVecMult(mat, *this);
1549 }
1550 template <typename T>
1551 template <typename S>
1552 SYS_FORCE_INLINE void
1554 {
1555  dest = ::rowVecMult(*this, mat);
1556 }
1557 
1558 template <typename T>
1559 static inline
1560 T dot(const UT_Matrix3T<T> &m1, const UT_Matrix3T<T> &m2){
1561  return m1.dot(m2);
1562 }
1563 
1564 template <typename T>
1565 inline
1567 {
1568  return UT_Matrix3T<T>(
1569  SYSmin(v1(0,0), v2(0,0)),
1570  SYSmin(v1(0,1), v2(0,1)),
1571  SYSmin(v1(0,2), v2(0,2)),
1572  SYSmin(v1(1,0), v2(1,0)),
1573  SYSmin(v1(1,1), v2(1,1)),
1574  SYSmin(v1(1,2), v2(1,2)),
1575  SYSmin(v1(2,0), v2(2,0)),
1576  SYSmin(v1(2,1), v2(2,1)),
1577  SYSmin(v1(2,2), v2(2,2))
1578  );
1579 }
1580 
1581 template <typename T>
1582 inline
1584 {
1585  return UT_Matrix3T<T>(
1586  SYSmax(v1(0,0), v2(0,0)),
1587  SYSmax(v1(0,1), v2(0,1)),
1588  SYSmax(v1(0,2), v2(0,2)),
1589  SYSmax(v1(1,0), v2(1,0)),
1590  SYSmax(v1(1,1), v2(1,1)),
1591  SYSmax(v1(1,2), v2(1,2)),
1592  SYSmax(v1(2,0), v2(2,0)),
1593  SYSmax(v1(2,1), v2(2,1)),
1594  SYSmax(v1(2,2), v2(2,2))
1595  );
1596 }
1597 
1598 template <typename T,typename S>
1599 inline
1601 {
1602  return UT_Matrix3T<T>(
1603  SYSlerp(v1(0,0), v2(0,0), t),
1604  SYSlerp(v1(0,1), v2(0,1), t),
1605  SYSlerp(v1(0,2), v2(0,2), t),
1606  SYSlerp(v1(1,0), v2(1,0), t),
1607  SYSlerp(v1(1,1), v2(1,1), t),
1608  SYSlerp(v1(1,2), v2(1,2), t),
1609  SYSlerp(v1(2,0), v2(2,0), t),
1610  SYSlerp(v1(2,1), v2(2,1), t),
1611  SYSlerp(v1(2,2), v2(2,2), t)
1612  );
1613 }
1614 
1615 #ifndef UT_DISABLE_VECTORIZE_MATRIX
1616 template <>
1617 inline
1619 {
1621  {
1622  const v4uf l(v1.data());
1623  const v4uf r(v2.data());
1624  vm_store(result.data(), SYSlerp(l, r, t).vector);
1625  }
1626  {
1627  const v4uf l(v1.data() + 4);
1628  const v4uf r(v2.data() + 4);
1629  vm_store(result.data() + 4, SYSlerp(l, r, t).vector);
1630  }
1631  {
1632  result(2,2) = SYSlerp(v1(2,2), v2(2,2), t);
1633  }
1634  return result;
1635 }
1636 #endif
1637 
1638 template<typename T>
1640 {
1642  typedef T DataType;
1643  static const exint TupleSize = 9;
1644  static const bool isVectorType = true;
1645 };
1646 
1647 // Overload for custom formatting of UT_Matrix3T<T> with UTformat.
1648 template<typename T>
1649 UT_API size_t format(char *buffer, size_t buffer_size, const UT_Matrix3T<T> &v);
1650 
1651 
1652 template <typename T> template<int ORDER>
1653 void
1654 UT_Matrix3T<T>::rotate(T rx, T ry, T rz)
1655 {
1656  switch(ORDER)
1657  {
1658  case 0://UT_XformOrder::XYZ:
1659  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1660  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1661  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1662  break;
1663 
1664  case 1:
1665  //case UT_XformOrder::XZY:
1666  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1667  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1668  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1669  break;
1670 
1671  case 2:
1672  //case UT_XformOrder::YXZ:
1673  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1674  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1675  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1676  break;
1677 
1678  case 3:
1679  //case UT_XformOrder::YZX:
1680  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1681  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1682  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1683  break;
1684 
1685  case 4:
1686  //case UT_XformOrder::ZXY:
1687  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1688  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1689  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1690  break;
1691 
1692  case 5:
1693  //case UT_XformOrder::ZYX:
1694  if(rz) rotate<UT_Axis3::ZAXIS>(rz);
1695  if(ry) rotate<UT_Axis3::YAXIS>(ry);
1696  if(rx) rotate<UT_Axis3::XAXIS>(rx);
1697  break;
1698 
1699  default:
1700  break;
1701  }
1702 }
1703 
1704 #endif
static int entries()
Returns the vector size.
Definition: UT_Matrix3.h:1222
UT_Vector3T< T > rowVecMult(const UT_Vector3T< T > &v, const UT_Matrix3T< S > &m)
Definition: UT_Matrix3.h:1477
SYS_FORCE_INLINE T & operator()(unsigned row, unsigned col) noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:1141
int isZero() const
Definition: UT_Matrix3.h:1118
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:575
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1221
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
UT_SymMatrix3T< T > averagedSymMatrix3() const
Convert this to a symmetric matrix, using averaged components.
Definition: UT_Matrix3.h:225
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: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:1161
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:548
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:1518
UT_Matrix3T< T > & operator*=(const UT_Matrix3T< T > &m)
Definition: UT_Matrix3.h:291
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:170
void extractScales(UT_Vector3F &scales, UT_Vector3F *shears=0)
Definition: UT_Matrix3.h:976
SYS_FORCE_INLINE T operator()(unsigned row, unsigned col) const noexcept
Return a matrix entry. No bounds checking on subscripts.
Definition: UT_Matrix3.h:1147
T determinant() const
Definition: UT_Matrix3.h:575
const GLuint GLenum const void * binary
Definition: glcorearb.h:1923
const GLfloat * c
Definition: glew.h:16631
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:1583
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:259
int isIdentity() const
Definition: UT_Matrix3.h:1106
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:1156
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:978
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:1792
UT_Matrix3T< T > SYSmin(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2)
Definition: UT_Matrix3.h:1566
2D Vector class.
Definition: UT_Vector2.h:149
void transpose()
Definition: UT_Matrix3.h:648
GLdouble GLdouble t
Definition: glew.h:1403
GLuint buffer
Definition: glcorearb.h:659
const T * data() const
Return the raw matrix data.
Definition: UT_Matrix3.h:1132
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:408
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:856
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: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:1024
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 T & y()
Definition: UT_Vector3.h:508
SYS_FORCE_INLINE void multiplyT(const UT_Matrix3T< S > &mat)
Definition: UT_Matrix3.h:1539
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:1102
UT_Matrix3T< T > SYSlerp(const UT_Matrix3T< T > &v1, const UT_Matrix3T< T > &v2, S t)
Definition: UT_Matrix3.h:1600
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:4347
GLfloat GLfloat GLfloat v2
Definition: glcorearb.h:817
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:170
SYS_FORCE_INLINE void scale(const UT_Vector3T< T > &s)
Definition: UT_Matrix3.h:856
const GLdouble * v
Definition: glcorearb.h:836
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:1392
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1221
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
SYS_FORCE_INLINE T & z()
Definition: UT_Vector3.h:510
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:1261
Definition: VM_SIMD.h:188
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:847
SYS_FORCE_INLINE void rowVecMult(const UT_Matrix3F &m)
Definition: UT_Matrix3.h:1506
SYS_FORCE_INLINE void outerproductUpdate(T b, const UT_Vector3D &v1, const UT_Vector3D &v2)
Definition: UT_Matrix3.h:443
GLfloat GLfloat p
Definition: glew.h:16656
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
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:815
SYS_FORCE_INLINE UT_Vector3T< T > & operator*=(const UT_Matrix3T< S > &m)
Definition: UT_Matrix3.h:1531
GA_API const UT_StringHolder orient
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:1413
bool SYSequalZero(const UT_Vector3T< T > &v)
Definition: UT_Vector3.h:844
void shear(T s_xy, T s_xz, T s_yz)
Definition: UT_Matrix3.h:1012
GLboolean * data
Definition: glcorearb.h:130
Inner class to access the elements symbolically.
IFDmantra py
Definition: HDK_Image.dox:266
GLuint GLfloat * val
Definition: glcorearb.h:1607
Quaternion class.
Definition: UT_Quaternion.h:51
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:275
void extractScales(UT_Vector3D &scales, UT_Vector3D *shears=0)
Definition: UT_Matrix3.h:974
UT_Vector3T< T > colVecMult(const UT_Matrix3T< S > &m, const UT_Vector3T< T > &v)
Definition: UT_Matrix3.h:1495
GA_API const UT_StringHolder pscale
GLenum GLenum void * row
Definition: glew.h:4995
unsigned hash() const
Compute a hash.
Definition: UT_Matrix3.h:1137
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:1925
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
SYS_FORCE_INLINE T & x()
Definition: UT_Vector3.h:506
T getEuclideanNorm() const
Definition: UT_Matrix3.h:1176
OIIO_FORCEINLINE const vint4 & operator-=(vint4 &a, const vint4 &b)
Definition: simd.h:4370
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:1104
void conditionRotate(UT_Vector3F *scales=0)
Definition: UT_Matrix3.h:961
void conditionRotate(UT_Vector3D *scales)
Definition: UT_Matrix3.h:963
#define const
Definition: zconf.h:214
GLfloat GLfloat v1
Definition: glcorearb.h:816
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:1094
SYS_FORCE_INLINE void prerotateHalf()
Definition: UT_Matrix3.h:817
GLboolean r
Definition: glcorearb.h:1221
SYS_FORCE_INLINE void multiply(UT_Vector3T< T > &dest, const UT_Matrix4T< S > &mat) const
Definition: UT_Matrix4.h:2030
UT_Matrix3T< T > operator/(const UT_Matrix3T< T > &mat, S sc)
Definition: UT_Matrix3.h:1445
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
GLdouble s
Definition: glew.h:1395
UT_FixedVector< T, 9 > FixedVectorType
Definition: UT_Matrix3.h:1641
unsigned int uint
Definition: SYS_Types.h:45
T trace() const
Definition: UT_Matrix3.h:581
GLint y
Definition: glcorearb.h:102
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
T * data()
Return the raw matrix data.
Definition: UT_Matrix3.h:1133