HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
UT_SymMatrix3.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  * NAME: UT_SymMatrix3.h (UT Library, C++)
7  *
8  * COMMENTS:
9  */
10 
11 #ifndef __UT_SYMMATRIX3_H_INCLUDED__
12 #define __UT_SYMMATRIX3_H_INCLUDED__
13 
14 #include "UT_API.h"
15 
16 #include "UT_Assert.h"
17 #include "UT_VectorTypes.h"
18 #include <SYS/SYS_Inline.h>
19 #include <SYS/SYS_Math.h> // for SYSlerp, ...
20 #include <SYS/SYS_StaticAssert.h>
21 #include <SYS/SYS_Types.h>
22 
23 #include <string.h> // for memset, ...
24 
25 
26 // Forward declaration
27 template <typename T> class UT_SymMatrix3T;
28 
29 // Free floating methods that operate on UT_SymMatrix3T
30 template <typename T>
32 template <typename T>
34 template <typename T>
36 template <typename T>
38 
39 
40 /// Generic symmetric 3x3 matrix
41 template <typename T>
42 class UT_SymMatrix3T
43 {
44 public:
45  typedef T value_type;
47  static constexpr int tuple_size = 6;
48 
49  /// Construct uninitialized matrix
51 
52  /// Construct matrix with uniform scale
53  explicit UT_SymMatrix3T<T>(T s)
54  {
55  setScale(s, s, s);
56  }
57 
58  /// Construct matrix with arbitrary scale
60  {
61  setScale(s.x(), s.y(), s.z());
62  }
63 
64  /// Convert from another floating point type.
65  template <typename S>
66  explicit UT_SymMatrix3T<T>(const UT_SymMatrix3T<S> &other)
67  {
68  for (int i = 0; i < tuple_size; ++i)
69  myV[i] = other.data()[i];
70  }
71 
72  /// Construct matrix with full components
74  T q00, T q10, T q11, T q20, T q21, T q22)
75  {
76  myLower.q00 = q00;
77  myLower.q10 = q10; myLower.q11 = q11;
78  myLower.q20 = q20; myLower.q21 = q21; myLower.q22 = q22;
79  }
80 
81  /// Create Householder Reflection matrix R such that R*M will be M with the
82  /// upper N components of column N zeroed out.
83  /// @note This is only useful when N is 1 or 2 for a 3x3 matrix.
84  template <int N>
86 
87  /// Set this to the zero matrix
88  inline void zero()
89  {
90  ::memset(&myV[0], 0, sizeof(myV));
91  }
92 
93  /// Set this to the identity matrix
94  inline void identity()
95  {
96  setScale(1, 1, 1);
97  }
98 
99  /// Return whether this is the identity matrix.
100  inline bool isIdentity() const
101  {
102  return myLower.q00 == 1.0f && myLower.q11 == 1.0f &&
103  myLower.q22 == 1.0f && myLower.q10 == 0.0f &&
104  myLower.q20 == 0.0f && myLower.q21 == 0.0f;
105  }
106 
107  /// Set this to a scale matrix
108  inline void setScale(T sx, T sy, T sz)
109  {
110  myLower.q00 = sx;
111  myLower.q11 = sy;
112  myLower.q22 = sz;
113  myLower.q10 = myLower.q20 = myLower.q21 = 0;
114  }
115  /// Set this to a scale matrix
116  inline void setScale(const UT_Vector3T<T>& s)
117  {
118  setScale(s.x(), s.y(), s.z());
119  }
120 
121  /// Return element (i,j)
122  inline T operator()(const int i, const int j) const
123  {
124  UT_ASSERT_P(i >= 0 && i < 3 && j >= 0 && j < 3);
125  if (i <= j)
126  return myV[(j*(j + 1))/2 + i];
127  else
128  return myV[(i*(i + 1))/2 + j];
129  }
130  /// Return reference to element (i,j)
131  inline T& operator()(const int i, const int j)
132  {
133  UT_ASSERT_P(i >= 0 && i < 3 && j >= 0 && j < 3);
134  if (i <= j)
135  return myV[(j*(j + 1))/2 + i];
136  else
137  return myV[(i*(i + 1))/2 + j];
138  }
139 
140  inline type& operator+=(const type& m)
141  {
142  for (int i = 0; i < tuple_size; ++i)
143  myV[i] += m.myV[i];
144  return *this;
145  }
146  inline type& operator-=(const type& m)
147  {
148  for (int i = 0; i < tuple_size; ++i)
149  myV[i] -= m.myV[i];
150  return *this;
151  }
152  inline type& operator*=(T scalar)
153  {
154  for (int i = 0; i < tuple_size; ++i)
155  myV[i] *= scalar;
156  return *this;
157  }
158  inline type& operator/=(T scalar)
159  {
160  return operator*=(1.0/scalar);
161  }
162 
163  /// Set this to a linear interpolation of the two given transforms:
164  /// *this = a + t*(b - a)
165  void lerp(const type& a, const type& b, T t)
166  {
167  for (int i = 0; i < 6; ++i)
168  myV[i] = SYSlerp(a.myV[i], b.myV[i], t);
169  }
170 
171  /// Inner class to access the elements symbolically
172  struct LowerTri
173  {
175  };
176  struct UpperTri
177  {
179  };
180 
181  /// Return the raw pointer to an array of tuple_size (6) elements
182  /// @{
183  const T* data() const { return &myV[0]; }
184  T* data() { return &myV[0]; }
185  /// @}
186 
187  /// Return reference to the lower triangular elements for symbolic access
188  const LowerTri & lowerTri() const { return myLower; }
189 
190  /// Return reference to the upper triangular elements for symbolic access
191  const UpperTri & upperTri() const { return myUpper; }
192 
193 
194  void transpose() {}
195 
196  // Sets the matrix to v * vT
197  void outerproduct(const UT_Vector3T<T> &v);
198  void outerproduct(T a, T b, T c);
199 
200  // Updates: Matrix += v * vT
201  void outerproductUpdate(const UT_Vector3T<T> &v);
202  void outerproductUpdate(T a, T b, T c);
203 
204  // Updates: Matrix += coef * v * vT
205  void outerproductUpdate(const UT_Vector3T<T> &v, T coef);
206  void outerproductUpdate(T a, T b, T c, T coef);
207 
208  // Calculates vT * Matrix * v
209  T vQv(const UT_Vector3T<T> &v) const;
210 
211 private:
212  // myV stores the elements of upper triangular portion of the symmetric
213  // matrix in a column-major form (or equivalently, the lower triangular
214  // portion in row-major form). The element (I, J) with I <= J, is stored
215  // at index: c = (J * (J + 1))/2 + I
216  // So the matrix is:
217  // myV[0] myV[1] myV[3]
218  // myV[1] myV[2] myV[4]
219  // myV[3] myV[4] myV[5]
220  //
221  union {
222  T myV[6];
225  };
226 
227  template <typename S> friend class UT_Matrix3T;
228  template <typename S> friend class UT_Matrix4T;
229 };
233 
234 ///////////////////////////////////////////////////////////////////////////////
235 //
236 // Implementations
237 //
238 
239 /// Return (m1 + m2)
240 template <typename T>
243 {
244  typedef typename UT_SymMatrix3T<T>::LowerTri LowerTri;
245  const LowerTri& x = m1.lowerTri();
246  const LowerTri& y = m2.lowerTri();
247  return UT_SymMatrix3T<T>(x.q00 + y.q00,
248  x.q10 + y.q10, x.q11 + y.q11,
249  x.q20 + y.q20, x.q21 + y.q21, x.q22 + y.q22);
250 }
251 
252 /// Return (m1 - m2)
253 template <typename T>
256 {
257  typedef typename UT_SymMatrix3T<T>::LowerTri LowerTri;
258  const LowerTri& x = m1.lowerTri();
259  const LowerTri& y = m2.lowerTri();
260  return UT_SymMatrix3T<T>(x.q00 - y.q00,
261  x.q10 - y.q10, x.q11 - y.q11,
262  x.q20 - y.q20, x.q21 - y.q21, x.q22 - y.q22);
263 }
264 
265 /// Return (m * s) for scalar s
266 template <typename T>
269 {
270  typedef typename UT_SymMatrix3T<T>::LowerTri LowerTri;
271  const LowerTri& l = m.lowerTri();
272  return UT_SymMatrix3T<T>(l.q00 * scale,
273  l.q10 * scale, l.q11 * scale,
274  l.q20 * scale, l.q21 * scale, l.q22 * scale);
275 }
276 
277 /// Create Householder Reflection matrix R such that R*M will be M with the
278 /// upper N components of column N zeroed out.
279 /// @note This is only useful when N is 1 or 2 for a 3x3 matrix.
280 template <typename T>
281 template <int N>
282 inline UT_SymMatrix3T<T>
284 {
285  // Adapted from Algorithm 5.1.1 (Householder Vector) in
286  // "Matrix Computations" (3rd Edition) by Golub and Van Loan.
287 
288  SYS_STATIC_ASSERT(N >= 1 && N <= 2);
290  T sigma;
291  if (N == 2)
292  {
293  v.assign(m(0,2), m(1,2), 1);
294  sigma = v(0)*v(0) + v(1)*v(1);
295  }
296  else if (N == 1)
297  {
298  v.assign(m(0,1), 1, 0);
299  sigma = v(0)*v(0);
300  }
301  if (sigma != 0)
302  {
303  T denom;
304  const T diag = m(N,N);
305  T mu = SYSsqrt(diag*diag + sigma);
306  if (diag <= 0)
307  denom = diag - mu;
308  else
309  denom = -sigma / (diag + mu);
310  v(0) /= denom;
311  if (N == 2)
312  v(1) /= denom;
313 
314  T beta = 2 * denom*denom / (sigma + denom*denom);
315  if (N == 2)
316  {
317  return UT_SymMatrix3T<T>(
318  1 - beta*v(0)*v(0),
319  - beta*v(0)*v(1), 1 - beta*v(1)*v(1),
320  - beta*v(0), - beta*v(1), 1 - beta);
321  }
322  else if (N == 1)
323  {
324  return UT_SymMatrix3T<T>(
325  1 - beta*v(0)*v(0),
326  - beta*v(0), 1 - beta,
327  0, 0, 1);
328  }
329  }
330  return UT_SymMatrix3T<T>(1); // identity
331 }
332 
333 /// Return (s * m) for scalar s
334 template <typename T>
337 {
338  typedef typename UT_SymMatrix3T<T>::LowerTri LowerTri;
339  const LowerTri& l = m.lowerTri();
340  return UT_SymMatrix3T<T>(l.q00 * scale,
341  l.q10 * scale, l.q11 * scale,
342  l.q20 * scale, l.q21 * scale, l.q22 * scale);
343 }
344 
345 template <typename T>
346 void
348 {
349  outerproduct(v.x(), v.y(), v.z());
350 }
351 
352 template <typename T>
353 void
355 {
356  myUpper.q00 = a * a; myUpper.q01 = a * b; myUpper.q02 = a * c;
357  myUpper.q11 = b * b; myUpper.q12 = b * c;
358  myUpper.q22 = c * c;
359 }
360 
361 template <typename T>
362 void
364 {
365  outerproductUpdate(v.x(), v.y(), v.z());
366 }
367 
368 template <typename T>
369 void
371 {
372  myUpper.q00 += a * a; myUpper.q01 += a * b; myUpper.q02 += a * c;
373  myUpper.q11 += b * b; myUpper.q12 += b * c;
374  myUpper.q22 += c * c;
375 
376 }
377 
378 template <typename T>
379 void
381 {
382  outerproductUpdate(v.x(), v.y(), v.z(), coef);
383 }
384 
385 template <typename T>
386 void
388 {
389  myUpper.q00 += coef * (a * a); myUpper.q01 += coef * (a * b);
390  myUpper.q02 += coef * (a * c);
391  myUpper.q11 += coef * (b * b); myUpper.q12 += coef * (b * c);
392  myUpper.q22 += coef * (c * c);
393 
394 }
395 
396 // Calculates vT this v
397 template <typename T>
398 T
400 {
401  T a = v.x(), b = v.y(), c = v.z();
402 
403  return (a * (a * myUpper.q00 + 2 * (b * myUpper.q01 + c * myUpper.q02)) +
404  b * (b * myUpper.q11 + 2 * (c * myUpper.q12)) +
405  c * (c * myUpper.q22 ));
406 }
407 
408 // Overload for custom formatting of UT_Matrix3T<T> with UTformat.
409 template<typename T>
410 UT_API size_t format(char *buffer, size_t buffer_size,
411  const UT_SymMatrix3T<T> &m);
412 
413 #endif // __UT_SYMMATRIX3_H_INCLUDED__
UT_SymMatrix3T< float > UT_SymMatrix3F
Mat3< typename promote< S, T >::type > operator*(S scalar, const Mat3< T > &m)
Multiply each element of the given matrix by scalar and return the result.
Definition: Mat3.h:561
UT_API size_t format(char *buffer, size_t buffer_size, const UT_SymMatrix3T< T > &m)
#define SYS_STATIC_ASSERT(expr)
T vQv(const UT_Vector3T< T > &v) const
const GLdouble * v
Definition: glcorearb.h:837
T & operator()(const int i, const int j)
Return reference to element (i,j)
UT_SymMatrix3T< T > type
Definition: UT_SymMatrix3.h:46
Mat3< typename promote< T0, T1 >::type > operator+(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Add corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:577
constexpr SYS_FORCE_INLINE T & z() noexcept
Definition: UT_Vector3.h:667
const LowerTri & lowerTri() const
Return reference to the lower triangular elements for symbolic access.
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
#define UT_API
Definition: UT_API.h:14
Generic symmetric 3x3 matrix.
Definition: UT_SymMatrix3.h:27
GLint y
Definition: glcorearb.h:103
UT_Matrix2T< T > SYSlerp(const UT_Matrix2T< T > &v1, const UT_Matrix2T< T > &v2, S t)
Definition: UT_Matrix2.h:675
void outerproduct(const UT_Vector3T< T > &v)
3D Vector class.
void outerproductUpdate(T b, const UT_Vector4T< S > &v1, const UT_Vector4T< S > &v2)
void zero()
Set this to the zero matrix.
Definition: UT_SymMatrix3.h:88
void identity()
Set this to the identity matrix.
Definition: UT_SymMatrix3.h:94
LowerTri myLower
static UT_SymMatrix3T< T > householderZeroUpper(const UT_Matrix3T< T > &m)
UT_SymMatrix3T< fpreal > UT_SymMatrix3R
GA_API const UT_StringHolder scale
type & operator+=(const type &m)
Definition: core.h:760
void setScale(T sx, T sy, T sz)
Set this to a scale matrix.
Mat3< typename promote< T0, T1 >::type > operator-(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Subtract corresponding elements of m0 and m1 and return the result.
Definition: Mat3.h:587
UT_SymMatrix3T< double > UT_SymMatrix3D
#define UT_ASSERT_P(ZZ)
Definition: UT_Assert.h:155
#define SYS_FORCE_INLINE
Definition: SYS_Inline.h:45
void setScale(const UT_Vector3T< T > &s)
Set this to a scale matrix.
T operator()(const int i, const int j) const
Return element (i,j)
const UpperTri & upperTri() const
Return reference to the upper triangular elements for symbolic access.
const T * data() const
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:1222
GLint GLenum GLint x
Definition: glcorearb.h:409
bool isIdentity() const
Return whether this is the identity matrix.
static constexpr int tuple_size
Definition: UT_SymMatrix3.h:47
GLdouble t
Definition: glad.h:2397
void lerp(const type &a, const type &b, T t)
Inner class to access the elements symbolically.
GLint j
Definition: glad.h:2733
void assign(T xx=0.0f, T yy=0.0f, T zz=0.0f)
Set the values of the vector components.
Definition: UT_Vector3.h:694
GA_API const UT_StringHolder N
void outerproductUpdate(const UT_Vector3T< T > &v)
UpperTri myUpper
type & operator/=(T scalar)
type & operator*=(T scalar)
constexpr SYS_FORCE_INLINE T & y() noexcept
Definition: UT_Vector3.h:665
type & operator-=(const type &m)
constexpr SYS_FORCE_INLINE T & x() noexcept
Definition: UT_Vector3.h:663