0027919: Visualization - support multiple transformation persistence groups within...
[occt.git] / src / NCollection / NCollection_Mat4.hxx
CommitLineData
30f0ad28 1// Created on: 2013-05-30
2// Created by: Anton POLETAEV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
30f0ad28 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
30f0ad28 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
30f0ad28 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
30f0ad28 15
16#ifndef _NCollection_Mat4_HeaderFile
17#define _NCollection_Mat4_HeaderFile
18
19#include <NCollection_Vec4.hxx>
a2af24d1 20#include <NCollection_Mat3.hxx>
30f0ad28 21
22//! Generic matrix of 4 x 4 elements.
23//! To be used in conjunction with NCollection_Vec4 entities.
a2af24d1 24//! Originally introduced for 3D space projection and orientation operations.
25//! Warning, empty constructor returns an identity matrix.
30f0ad28 26template<typename Element_t>
27class NCollection_Mat4
28{
30f0ad28 29public:
30
31 //! Get number of rows.
32 //! @return number of rows.
33 static size_t Rows()
34 {
35 return 4;
36 }
37
38 //! Get number of columns.
39 //! @retur number of columns.
40 static size_t Cols()
41 {
42 return 4;
43 }
44
a2af24d1 45 //! Return identity matrix.
46 static NCollection_Mat4 Identity()
47 {
48 return NCollection_Mat4();
49 }
50
51 //! Return zero matrix.
52 static NCollection_Mat4 Zero()
53 {
54 NCollection_Mat4 aMat; aMat.InitZero();
55 return aMat;
56 }
57
58public:
59
30f0ad28 60 //! Empty constructor.
a2af24d1 61 //! Construct the identity matrix.
30f0ad28 62 NCollection_Mat4()
63 {
64 InitIdentity();
65 }
66
f9b30c0d 67 //! Conversion constructor (explicitly converts some 4 x 4 matrix with other element type
68 //! to a new 4 x 4 matrix with the element type Element_t,
69 //! whose elements are static_cast'ed corresponding elements of theOtherMat4 matrix)
70 //! @tparam OtherElement_t the element type of the other 4 x 4 matrix theOtherVec4
71 //! @param theOtherMat4 the 4 x 4 matrix that needs to be converted
72 template <typename OtherElement_t>
73 explicit NCollection_Mat4 (const NCollection_Mat4<OtherElement_t>& theOtherMat4)
74 {
75 ConvertFrom (theOtherMat4);
76 }
77
30f0ad28 78 //! Get element at the specified row and column.
a2af24d1 79 //! @param theRow [in] the row to address.
30f0ad28 80 //! @param theCol [in] the column to address.
81 //! @return the value of the addressed element.
82 Element_t GetValue (const size_t theRow, const size_t theCol) const
83 {
84 return myMat[theCol * 4 + theRow];
85 }
86
87 //! Access element at the specified row and column.
a2af24d1 88 //! @param theRow [in] the row to access.
30f0ad28 89 //! @param theCol [in] the column to access.
90 //! @return reference on the matrix element.
91 Element_t& ChangeValue (const size_t theRow, const size_t theCol)
92 {
93 return myMat[theCol * 4 + theRow];
94 }
95
96 //! Set value for the element specified by row and columns.
97 //! @param theRow [in] the row to change.
98 //! @param theCol [in] the column to change.
a2af24d1 99 //! @param theValue [in] the value to set.
30f0ad28 100 void SetValue (const size_t theRow,
101 const size_t theCol,
102 const Element_t theValue)
103 {
104 myMat[theCol * 4 + theRow] = theValue;
105 }
106
a2af24d1 107 //! Return value.
108 Element_t& operator() (const size_t theRow, const size_t theCol) { return ChangeValue (theRow, theCol); }
109
110 //! Return value.
111 Element_t operator() (const size_t theRow, const size_t theCol) const { return GetValue (theRow, theCol); }
112
30f0ad28 113 //! Get vector of elements for the specified row.
114 //! @param theRow [in] the row to access.
115 //! @return vector of elements.
116 NCollection_Vec4<Element_t> GetRow (const size_t theRow) const
117 {
118 return NCollection_Vec4<Element_t> (GetValue (theRow, 0),
119 GetValue (theRow, 1),
120 GetValue (theRow, 2),
121 GetValue (theRow, 3));
122 }
123
124 //! Change first 3 row values by the passed vector.
125 //! @param theRow [in] the row to change.
126 //! @param theVec [in] the vector of values.
127 void SetRow (const size_t theRow, const NCollection_Vec3<Element_t>& theVec)
128 {
129 SetValue (theRow, 0, theVec.x());
130 SetValue (theRow, 1, theVec.y());
131 SetValue (theRow, 2, theVec.z());
132 }
133
134 //! Set row values by the passed 4 element vector.
135 //! @param theRow [in] the row to change.
136 //! @param theVec [in] the vector of values.
137 void SetRow (const size_t theRow, const NCollection_Vec4<Element_t>& theVec)
138 {
139 SetValue (theRow, 0, theVec.x());
140 SetValue (theRow, 1, theVec.y());
141 SetValue (theRow, 2, theVec.z());
142 SetValue (theRow, 3, theVec.w());
143 }
144
145 //! Get vector of elements for the specified column.
146 //! @param theCol [in] the column to access.
147 //! @return vector of elements.
148 NCollection_Vec4<Element_t> GetColumn (const size_t theCol) const
149 {
150 return NCollection_Vec4<Element_t> (GetValue (0, theCol),
151 GetValue (1, theCol),
152 GetValue (2, theCol),
153 GetValue (3, theCol));
154 }
155
156 //! Change first 3 column values by the passed vector.
157 //! @param theCol [in] the column to change.
158 //! @param theVec [in] the vector of values.
159 void SetColumn (const size_t theCol,
160 const NCollection_Vec3<Element_t>& theVec)
161 {
162 SetValue (0, theCol, theVec.x());
163 SetValue (1, theCol, theVec.y());
164 SetValue (2, theCol, theVec.z());
165 }
166
167 //! Set column values by the passed 4 element vector.
168 //! @param theCol [in] the column to change.
169 //! @param theVec [in] the vector of values.
170 void SetColumn (const size_t theCol,
171 const NCollection_Vec4<Element_t>& theVec)
172 {
173 SetValue (0, theCol, theVec.x());
174 SetValue (1, theCol, theVec.y());
175 SetValue (2, theCol, theVec.z());
176 SetValue (3, theCol, theVec.w());
177 }
178
179 //! Get vector of diagonal elements.
a2af24d1 180 //! @return vector of diagonal elements.
30f0ad28 181 NCollection_Vec4<Element_t> GetDiagonal() const
182 {
183 return NCollection_Vec4<Element_t> (GetValue (0, 0),
184 GetValue (1, 1),
185 GetValue (2, 2),
186 GetValue (3, 3));
187 }
188
189 //! Change first 3 elements of the diagonal matrix.
190 //! @param theVec the vector of values.
191 void SetDiagonal (const NCollection_Vec3<Element_t>& theVec)
192 {
193 SetValue (0, 0, theVec.x());
194 SetValue (1, 1, theVec.y());
195 SetValue (2, 2, theVec.z());
196 }
197
198 //! Set diagonal elements of the matrix by the passed vector.
199 //! @param theVec [in] the vector of values.
200 void SetDiagonal (const NCollection_Vec4<Element_t>& theVec)
201 {
202 SetValue (0, 0, theVec.x());
203 SetValue (1, 1, theVec.y());
204 SetValue (2, 2, theVec.z());
205 SetValue (3, 3, theVec.w());
206 }
207
a2af24d1 208 //! Return 3x3 sub-matrix.
209 NCollection_Mat3<Element_t> GetMat3() const
210 {
211 NCollection_Mat3<Element_t> aMat;
212 aMat.SetColumn (0, GetColumn (0).xyz());
213 aMat.SetColumn (1, GetColumn (1).xyz());
214 aMat.SetColumn (2, GetColumn (2).xyz());
215 return aMat;
216 }
217
218 //! Initialize the zero matrix.
219 void InitZero()
220 {
221 std::memcpy (this, MyZeroArray, sizeof (NCollection_Mat4));
222 }
223
224 //! Checks the matrix for zero (without tolerance).
225 bool IsZero() const
226 {
227 return std::memcmp (this, MyZeroArray, sizeof (NCollection_Mat4)) == 0;
228 }
229
30f0ad28 230 //! Initialize the identity matrix.
231 void InitIdentity()
232 {
a2af24d1 233 std::memcpy (this, MyIdentityArray, sizeof (NCollection_Mat4));
197ac94e 234 }
30f0ad28 235
a2af24d1 236 //! Checks the matrix for identity (without tolerance).
197ac94e 237 bool IsIdentity() const
238 {
a2af24d1 239 return std::memcmp (this, MyIdentityArray, sizeof (NCollection_Mat4)) == 0;
30f0ad28 240 }
241
8613985b 242 //! Check this matrix for equality with another matrix (without tolerance!).
243 bool IsEqual (const NCollection_Mat4& theOther) const
244 {
245 return std::memcmp (this, &theOther, sizeof(NCollection_Mat4)) == 0;
246 }
247
248 //! Check this matrix for equality with another matrix (without tolerance!).
8613985b 249 bool operator== (const NCollection_Mat4& theOther) const { return IsEqual (theOther); }
250
251 //! Check this matrix for non-equality with another matrix (without tolerance!).
8613985b 252 bool operator!= (const NCollection_Mat4& theOther) const { return !IsEqual (theOther); }
253
a2af24d1 254 //! Raw access to the data (for OpenGL exchange);
255 //! the data is returned in column-major order.
938d4544 256 const Element_t* GetData() const { return myMat; }
257 Element_t* ChangeData() { return myMat; }
30f0ad28 258
259 //! Multiply by the vector (M * V).
260 //! @param theVec [in] the vector to multiply.
261 NCollection_Vec4<Element_t> operator* (const NCollection_Vec4<Element_t>& theVec) const
262 {
263 return NCollection_Vec4<Element_t> (
264 GetValue (0, 0) * theVec.x() + GetValue (0, 1) * theVec.y() + GetValue (0, 2) * theVec.z() + GetValue (0, 3) * theVec.w(),
265 GetValue (1, 0) * theVec.x() + GetValue (1, 1) * theVec.y() + GetValue (1, 2) * theVec.z() + GetValue (1, 3) * theVec.w(),
266 GetValue (2, 0) * theVec.x() + GetValue (2, 1) * theVec.y() + GetValue (2, 2) * theVec.z() + GetValue (2, 3) * theVec.w(),
267 GetValue (3, 0) * theVec.x() + GetValue (3, 1) * theVec.y() + GetValue (3, 2) * theVec.z() + GetValue (3, 3) * theVec.w());
268 }
269
270 //! Compute matrix multiplication product: A * B.
271 //! @param theMatA [in] the matrix "A".
272 //! @param theMatB [in] the matrix "B".
a2af24d1 273 static NCollection_Mat4 Multiply (const NCollection_Mat4& theMatA,
274 const NCollection_Mat4& theMatB)
30f0ad28 275 {
276 NCollection_Mat4 aMatRes;
277
278 size_t aInputElem;
279 for (size_t aResElem = 0; aResElem < 16; ++aResElem)
280 {
a2af24d1 281 aMatRes.myMat[aResElem] = (Element_t )0;
30f0ad28 282 for (aInputElem = 0; aInputElem < 4; ++aInputElem)
283 {
a2af24d1 284 aMatRes.myMat[aResElem] += theMatA.GetValue(aResElem % 4, aInputElem)
285 * theMatB.GetValue(aInputElem, aResElem / 4);
30f0ad28 286 }
287 }
288
289 return aMatRes;
290 }
291
292 //! Compute matrix multiplication.
293 //! @param theMat [in] the matrix to multiply.
294 void Multiply (const NCollection_Mat4& theMat)
295 {
296 *this = Multiply(*this, theMat);
297 }
298
299 //! Multiply by the another matrix.
300 //! @param theMat [in] the other matrix.
301 NCollection_Mat4& operator*= (const NCollection_Mat4& theMat)
302 {
303 Multiply (theMat);
304 return *this;
305 }
306
307 //! Compute matrix multiplication product.
308 //! @param theMat [in] the other matrix.
309 //! @return result of multiplication.
a2af24d1 310 Standard_NODISCARD NCollection_Mat4 operator* (const NCollection_Mat4& theMat) const
30f0ad28 311 {
938d4544 312 return Multiplied (theMat);
30f0ad28 313 }
314
315 //! Compute matrix multiplication product.
316 //! @param theMat [in] the other matrix.
317 //! @return result of multiplication.
a2af24d1 318 Standard_NODISCARD NCollection_Mat4 Multiplied (const NCollection_Mat4& theMat) const
30f0ad28 319 {
320 NCollection_Mat4 aTempMat (*this);
321 aTempMat *= theMat;
322 return aTempMat;
323 }
324
325 //! Compute per-component multiplication.
326 //! @param theFactor [in] the scale factor.
327 void Multiply (const Element_t theFactor)
328 {
329 for (size_t i = 0; i < 16; ++i)
330 {
331 myMat[i] *= theFactor;
332 }
333 }
334
335 //! Compute per-element multiplication.
336 //! @param theFactor [in] the scale factor.
a2af24d1 337 NCollection_Mat4& operator*= (const Element_t theFactor)
30f0ad28 338 {
339 Multiply (theFactor);
340 return *this;
341 }
342
343 //! Compute per-element multiplication.
344 //! @param theFactor [in] the scale factor.
a2af24d1 345 //! @return the result of multiplication.
346 Standard_NODISCARD NCollection_Mat4 operator* (const Element_t theFactor) const
30f0ad28 347 {
348 return Multiplied (theFactor);
349 }
350
351 //! Compute per-element multiplication.
352 //! @param theFactor [in] the scale factor.
a2af24d1 353 //! @return the result of multiplication.
354 Standard_NODISCARD NCollection_Mat4 Multiplied (const Element_t theFactor) const
30f0ad28 355 {
356 NCollection_Mat4 aTempMat (*this);
357 aTempMat *= theFactor;
358 return aTempMat;
359 }
360
a2af24d1 361 //! Compute per-component division.
362 //! @param theFactor [in] the scale factor.
363 void Divide (const Element_t theFactor)
364 {
365 for (size_t i = 0; i < 16; ++i)
366 {
367 myMat[i] /= theFactor;
368 }
369 }
370
371 //! Per-component division.
372 //! @param theScalar [in] the scale factor.
373 NCollection_Mat4& operator/= (const Element_t theScalar)
374 {
375 Divide (theScalar);
376 return *this;
377 }
378
379 //! Divides all the coefficients of the matrix by scalar.
380 Standard_NODISCARD NCollection_Mat4 Divided (const Element_t theScalar) const
381 {
382 NCollection_Mat4 aTempMat (*this);
383 aTempMat /= theScalar;
384 return aTempMat;
385 }
386
387 //! Divides all the coefficients of the matrix by scalar.
388 Standard_NODISCARD NCollection_Mat4 operator/ (const Element_t theScalar) const
389 {
390 return Divided (theScalar);
391 }
392
393 //! Per-component addition of another matrix.
394 void Add (const NCollection_Mat4& theMat)
395 {
396 for (size_t i = 0; i < 16; ++i)
397 {
398 myMat[i] += theMat.myMat[i];
399 }
400 }
401
402 //! Per-component addition of another matrix.
403 NCollection_Mat4& operator+= (const NCollection_Mat4& theMat)
404 {
405 Add (theMat);
406 return *this;
407 }
408
409 //! Per-component subtraction of another matrix.
410 void Subtract (const NCollection_Mat4& theMat)
411 {
412 for (size_t i = 0; i < 16; ++i)
413 {
414 myMat[i] -= theMat.myMat[i];
415 }
416 }
417
418 //! Per-component subtraction of another matrix.
419 NCollection_Mat4& operator-= (const NCollection_Mat4& theMat)
420 {
421 Subtract (theMat);
422 return *this;
423 }
424
425 //! Per-component addition of another matrix.
426 Standard_NODISCARD NCollection_Mat4 Added (const NCollection_Mat4& theMat) const
427 {
428 NCollection_Mat4 aMat (*this);
429 aMat += theMat;
430 return aMat;
431 }
432
433 //! Per-component addition of another matrix.
434 Standard_NODISCARD NCollection_Mat4 operator+ (const NCollection_Mat4& theMat) const { return Added (theMat); }
435
436 //! Per-component subtraction of another matrix.
437 Standard_NODISCARD NCollection_Mat4 Subtracted (const NCollection_Mat4& theMat) const
438 {
439 NCollection_Mat4 aMat (*this);
440 aMat -= theMat;
441 return aMat;
442 }
443
444 //! Per-component subtraction of another matrix.
445 Standard_NODISCARD NCollection_Mat4 operator- (const NCollection_Mat4& theMat) const { return Subtracted (theMat); }
446
447 //! Returns matrix with all components negated.
448 Standard_NODISCARD NCollection_Mat4 Negated() const
449 {
450 NCollection_Mat4 aMat;
451 for (size_t i = 0; i < 16; ++i)
452 {
453 aMat.myMat[i] = -myMat[i];
454 }
455 return aMat;
456 }
457
458 //! Returns matrix with all components negated.
459 Standard_NODISCARD NCollection_Mat4 operator-() const { return Negated(); }
460
30f0ad28 461 //! Translate the matrix on the passed vector.
462 //! @param theVec [in] the translation vector.
463 void Translate (const NCollection_Vec3<Element_t>& theVec)
464 {
465 NCollection_Mat4 aTempMat;
466 aTempMat.SetColumn (3, theVec);
467 this->Multiply (aTempMat);
468 }
469
938d4544 470 //! Transpose the matrix.
471 //! @return transposed copy of the matrix.
a2af24d1 472 Standard_NODISCARD NCollection_Mat4 Transposed() const
938d4544 473 {
474 NCollection_Mat4 aTempMat;
475 aTempMat.SetRow (0, GetColumn (0));
476 aTempMat.SetRow (1, GetColumn (1));
477 aTempMat.SetRow (2, GetColumn (2));
478 aTempMat.SetRow (3, GetColumn (3));
479 return aTempMat;
480 }
481
482 //! Transpose the matrix.
483 void Transpose()
484 {
485 *this = Transposed();
486 }
487
30f0ad28 488 //! Compute inverted matrix.
a2af24d1 489 //! @param theOutMx [out] the inverted matrix
490 //! @param theDet [out] determinant of matrix
491 //! @return true if reversion success
492 bool Inverted (NCollection_Mat4<Element_t>& theOutMx, Element_t& theDet) const
30f0ad28 493 {
494 Element_t* inv = theOutMx.myMat;
495
496 // use short-cut for better readability
497 const Element_t* m = myMat;
498
499 inv[ 0] = m[ 5] * (m[10] * m[15] - m[11] * m[14]) -
500 m[ 9] * (m[ 6] * m[15] - m[ 7] * m[14]) -
501 m[13] * (m[ 7] * m[10] - m[ 6] * m[11]);
502
503 inv[ 1] = m[ 1] * (m[11] * m[14] - m[10] * m[15]) -
504 m[ 9] * (m[ 3] * m[14] - m[ 2] * m[15]) -
505 m[13] * (m[ 2] * m[11] - m[ 3] * m[10]);
506
507 inv[ 2] = m[ 1] * (m[ 6] * m[15] - m[ 7] * m[14]) -
508 m[ 5] * (m[ 2] * m[15] - m[ 3] * m[14]) -
509 m[13] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
510
511 inv[ 3] = m[ 1] * (m[ 7] * m[10] - m[ 6] * m[11]) -
512 m[ 5] * (m[ 3] * m[10] - m[ 2] * m[11]) -
513 m[ 9] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
514
515 inv[ 4] = m[ 4] * (m[11] * m[14] - m[10] * m[15]) -
516 m[ 8] * (m[ 7] * m[14] - m[ 6] * m[15]) -
517 m[12] * (m[ 6] * m[11] - m[ 7] * m[10]);
518
519 inv[ 5] = m[ 0] * (m[10] * m[15] - m[11] * m[14]) -
520 m[ 8] * (m[ 2] * m[15] - m[ 3] * m[14]) -
521 m[12] * (m[ 3] * m[10] - m[ 2] * m[11]);
522
523 inv[ 6] = m[ 0] * (m[ 7] * m[14] - m[ 6] * m[15]) -
524 m[ 4] * (m[ 3] * m[14] - m[ 2] * m[15]) -
525 m[12] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
526
527 inv[ 7] = m[ 0] * (m[ 6] * m[11] - m[ 7] * m[10]) -
528 m[ 4] * (m[ 2] * m[11] - m[ 3] * m[10]) -
529 m[ 8] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
530
531 inv[ 8] = m[ 4] * (m[ 9] * m[15] - m[11] * m[13]) -
532 m[ 8] * (m[ 5] * m[15] - m[ 7] * m[13]) -
533 m[12] * (m[ 7] * m[ 9] - m[ 5] * m[11]);
534
535 inv[ 9] = m[ 0] * (m[11] * m[13] - m[ 9] * m[15]) -
536 m[ 8] * (m[ 3] * m[13] - m[ 1] * m[15]) -
537 m[12] * (m[ 1] * m[11] - m[ 3] * m[ 9]);
538
539 inv[10] = m[ 0] * (m[ 5] * m[15] - m[ 7] * m[13]) -
540 m[ 4] * (m[ 1] * m[15] - m[ 3] * m[13]) -
541 m[12] * (m[ 3] * m[ 5] - m[ 1] * m[ 7]);
542
543 inv[11] = m[ 0] * (m[ 7] * m[ 9] - m[ 5] * m[11]) -
544 m[ 4] * (m[ 3] * m[ 9] - m[ 1] * m[11]) -
545 m[ 8] * (m[ 1] * m[ 7] - m[ 3] * m[ 5]);
546
547 inv[12] = m[ 4] * (m[10] * m[13] - m[ 9] * m[14]) -
548 m[ 8] * (m[ 6] * m[13] - m[ 5] * m[14]) -
549 m[12] * (m[ 5] * m[10] - m[ 6] * m[ 9]);
550
551 inv[13] = m[ 0] * (m[ 9] * m[14] - m[10] * m[13]) -
552 m[ 8] * (m[ 1] * m[14] - m[ 2] * m[13]) -
553 m[12] * (m[ 2] * m[ 9] - m[ 1] * m[10]);
554
555 inv[14] = m[ 0] * (m[ 6] * m[13] - m[ 5] * m[14]) -
556 m[ 4] * (m[ 2] * m[13] - m[ 1] * m[14]) -
557 m[12] * (m[ 1] * m[ 6] - m[ 2] * m[ 5]);
558
559 inv[15] = m[ 0] * (m[ 5] * m[10] - m[ 6] * m[ 9]) -
560 m[ 4] * (m[ 1] * m[10] - m[ 2] * m[ 9]) -
561 m[ 8] * (m[ 2] * m[ 5] - m[ 1] * m[ 6]);
562
a2af24d1 563 theDet = m[0] * inv[ 0] +
564 m[1] * inv[ 4] +
565 m[2] * inv[ 8] +
566 m[3] * inv[12];
567 if (theDet == 0)
568 {
30f0ad28 569 return false;
a2af24d1 570 }
30f0ad28 571
a2af24d1 572 const Element_t aDiv = (Element_t) 1. / theDet;
30f0ad28 573 for (int i = 0; i < 16; ++i)
a2af24d1 574 {
575 inv[i] *= aDiv;
576 }
30f0ad28 577 return true;
578 }
579
a2af24d1 580 //! Compute inverted matrix.
581 //! @param theOutMx [out] the inverted matrix
582 //! @return true if reversion success
583 bool Inverted (NCollection_Mat4<Element_t>& theOutMx) const
584 {
585 Element_t aDet;
586 return Inverted (theOutMx, aDet);
587 }
588
589 //! Return inverted matrix.
590 NCollection_Mat4 Inverted() const
591 {
592 NCollection_Mat4 anInv;
593 if (!Inverted (anInv))
594 {
595 throw Standard_ConstructionError ("NCollection_Mat4::Inverted() - matrix has zero determinant");
596 }
597 return anInv;
598 }
599
4e993e4d 600 //! Return determinant of the 3x3 sub-matrix.
601 Element_t DeterminantMat3() const
602 {
603 return (GetValue (0, 0) * GetValue (1, 1) * GetValue (2, 2)
604 + GetValue (0, 1) * GetValue (1, 2) * GetValue (2, 0)
605 + GetValue (0, 2) * GetValue (1, 0) * GetValue (2, 1))
606 - (GetValue (0, 2) * GetValue (1, 1) * GetValue (2, 0)
607 + GetValue (0, 0) * GetValue (1, 2) * GetValue (2, 1)
608 + GetValue (0, 1) * GetValue (1, 0) * GetValue (2, 2));
609 }
610
a2af24d1 611 //! Return adjoint (adjugate matrix, e.g. conjugate transpose).
612 Standard_NODISCARD NCollection_Mat4<Element_t> Adjoint() const
613 {
614 NCollection_Mat4<Element_t> aMat;
615 aMat.SetRow (0, crossVec4 ( GetRow (1), GetRow (2), GetRow (3)));
616 aMat.SetRow (1, crossVec4 (-GetRow (0), GetRow (2), GetRow (3)));
617 aMat.SetRow (2, crossVec4 ( GetRow (0), GetRow (1), GetRow (3)));
618 aMat.SetRow (3, crossVec4 (-GetRow (0), GetRow (1), GetRow (2)));
619 return aMat;
620 }
621
778cd667 622 //! Take values from NCollection_Mat4 with a different element type with type conversion.
c827ea3a 623 template <typename Other_t>
778cd667 624 void ConvertFrom (const NCollection_Mat4<Other_t>& theFrom)
c827ea3a 625 {
626 for (int anIdx = 0; anIdx < 16; ++anIdx)
627 {
778cd667 628 myMat[anIdx] = static_cast<Element_t> (theFrom.myMat[anIdx]);
c827ea3a 629 }
630 }
631
778cd667 632 //! Take values from NCollection_Mat4 with a different element type with type conversion.
633 template <typename Other_t>
634 void Convert (const NCollection_Mat4<Other_t>& theFrom) { ConvertFrom (theFrom); }
635
c827ea3a 636 //! Maps plain C array to matrix type.
637 static NCollection_Mat4<Element_t>& Map (Element_t* theData)
638 {
639 return *reinterpret_cast<NCollection_Mat4<Element_t>*> (theData);
640 }
641
642 //! Maps plain C array to matrix type.
643 static const NCollection_Mat4<Element_t>& Map (const Element_t* theData)
644 {
645 return *reinterpret_cast<const NCollection_Mat4<Element_t>*> (theData);
646 }
647
bc73b006 648 //! Dumps the content of me into the stream
649 void DumpJson (Standard_OStream& theOStream, Standard_Integer) const
650 {
651 OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "NCollection_Mat4", 16,
652 GetValue (0, 0), GetValue (0, 1), GetValue (0, 2), GetValue (0, 3),
653 GetValue (1, 0), GetValue (1, 1), GetValue (1, 2), GetValue (1, 3),
654 GetValue (2, 0), GetValue (2, 1), GetValue (2, 2), GetValue (2, 3),
655 GetValue (3, 0), GetValue (3, 1), GetValue (3, 2), GetValue (3, 3))
656 }
657
a2af24d1 658private:
659
660 //! Cross-product has no direct meaning in 4D space - provided for local usage.
661 static NCollection_Vec4<Element_t> crossVec4 (const NCollection_Vec4<Element_t>& theA,
662 const NCollection_Vec4<Element_t>& theB,
663 const NCollection_Vec4<Element_t>& theC)
664 {
665 const Element_t aD1 = (theB.z() * theC.w()) - (theB.w() * theC.z());
666 const Element_t aD2 = (theB.y() * theC.w()) - (theB.w() * theC.y());
667 const Element_t aD3 = (theB.y() * theC.z()) - (theB.z() * theC.y());
668 const Element_t aD4 = (theB.x() * theC.w()) - (theB.w() * theC.x());
669 const Element_t aD5 = (theB.x() * theC.z()) - (theB.z() * theC.x());
670 const Element_t aD6 = (theB.x() * theC.y()) - (theB.y() * theC.x());
671
672 NCollection_Vec4<Element_t> aVec;
673 aVec.x() = -theA.y() * aD1 + theA.z() * aD2 - theA.w() * aD3;
674 aVec.y() = theA.x() * aD1 - theA.z() * aD4 + theA.w() * aD5;
675 aVec.z() = -theA.x() * aD2 + theA.y() * aD4 - theA.w() * aD6;
676 aVec.w() = theA.x() * aD3 - theA.y() * aD5 + theA.z() * aD6;
677 return aVec;
678 }
679
30f0ad28 680private:
681
682 Element_t myMat[16];
683
197ac94e 684private:
685
a2af24d1 686 static const Element_t MyZeroArray[16];
687 static const Element_t MyIdentityArray[16];
c827ea3a 688
689 // All instantiations are friend to each other
690 template<class OtherType> friend class NCollection_Mat4;
691
30f0ad28 692};
693
197ac94e 694template<typename Element_t>
a2af24d1 695const Element_t NCollection_Mat4<Element_t>::MyZeroArray[] =
696 {0, 0, 0, 0,
697 0, 0, 0, 0,
698 0, 0, 0, 0,
699 0, 0, 0, 0};
700
701template<typename Element_t>
702const Element_t NCollection_Mat4<Element_t>::MyIdentityArray[] =
197ac94e 703 {1, 0, 0, 0,
704 0, 1, 0, 0,
705 0, 0, 1, 0,
706 0, 0, 0, 1};
707
8613985b 708#if defined(_MSC_VER) && (_MSC_VER >= 1900)
709 #include <type_traits>
710
711 static_assert(std::is_trivially_copyable<NCollection_Mat4<float>>::value, "NCollection_Mat4 is not is_trivially_copyable() structure!");
712 static_assert(std::is_standard_layout <NCollection_Mat4<float>>::value, "NCollection_Mat4 is not is_standard_layout() structure!");
a2af24d1 713 static_assert(sizeof(NCollection_Mat4<float>) == sizeof(float)*16, "NCollection_Mat4 is not packed/aligned!");
8613985b 714#endif
715
938d4544 716#endif // _NCollection_Mat4_HeaderFile