1 // Created on: 2013-05-30
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
16 #ifndef _NCollection_Mat4_HeaderFile
17 #define _NCollection_Mat4_HeaderFile
19 #include <NCollection_Vec4.hxx>
20 #include <NCollection_Mat3.hxx>
22 //! Generic matrix of 4 x 4 elements.
23 //! To be used in conjunction with NCollection_Vec4 entities.
24 //! Originally introduced for 3D space projection and orientation operations.
25 //! Warning, empty constructor returns an identity matrix.
26 template<typename Element_t>
27 class NCollection_Mat4
31 //! Get number of rows.
32 //! @return number of rows.
38 //! Get number of columns.
39 //! @retur number of columns.
45 //! Return identity matrix.
46 static NCollection_Mat4 Identity()
48 return NCollection_Mat4();
51 //! Return zero matrix.
52 static NCollection_Mat4 Zero()
54 NCollection_Mat4 aMat; aMat.InitZero();
60 //! Empty constructor.
61 //! Construct the identity matrix.
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)
75 ConvertFrom (theOtherMat4);
78 //! Get element at the specified row and column.
79 //! @param theRow [in] the row to address.
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
84 return myMat[theCol * 4 + theRow];
87 //! Access element at the specified row and column.
88 //! @param theRow [in] the row to access.
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)
93 return myMat[theCol * 4 + theRow];
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.
99 //! @param theValue [in] the value to set.
100 void SetValue (const size_t theRow,
102 const Element_t theValue)
104 myMat[theCol * 4 + theRow] = theValue;
108 Element_t& operator() (const size_t theRow, const size_t theCol) { return ChangeValue (theRow, theCol); }
111 Element_t operator() (const size_t theRow, const size_t theCol) const { return GetValue (theRow, theCol); }
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
118 return NCollection_Vec4<Element_t> (GetValue (theRow, 0),
119 GetValue (theRow, 1),
120 GetValue (theRow, 2),
121 GetValue (theRow, 3));
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)
129 SetValue (theRow, 0, theVec.x());
130 SetValue (theRow, 1, theVec.y());
131 SetValue (theRow, 2, theVec.z());
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)
139 SetValue (theRow, 0, theVec.x());
140 SetValue (theRow, 1, theVec.y());
141 SetValue (theRow, 2, theVec.z());
142 SetValue (theRow, 3, theVec.w());
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
150 return NCollection_Vec4<Element_t> (GetValue (0, theCol),
151 GetValue (1, theCol),
152 GetValue (2, theCol),
153 GetValue (3, theCol));
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)
162 SetValue (0, theCol, theVec.x());
163 SetValue (1, theCol, theVec.y());
164 SetValue (2, theCol, theVec.z());
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)
173 SetValue (0, theCol, theVec.x());
174 SetValue (1, theCol, theVec.y());
175 SetValue (2, theCol, theVec.z());
176 SetValue (3, theCol, theVec.w());
179 //! Get vector of diagonal elements.
180 //! @return vector of diagonal elements.
181 NCollection_Vec4<Element_t> GetDiagonal() const
183 return NCollection_Vec4<Element_t> (GetValue (0, 0),
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)
193 SetValue (0, 0, theVec.x());
194 SetValue (1, 1, theVec.y());
195 SetValue (2, 2, theVec.z());
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)
202 SetValue (0, 0, theVec.x());
203 SetValue (1, 1, theVec.y());
204 SetValue (2, 2, theVec.z());
205 SetValue (3, 3, theVec.w());
208 //! Return 3x3 sub-matrix.
209 NCollection_Mat3<Element_t> GetMat3() const
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());
218 //! Initialize the zero matrix.
221 std::memcpy (this, MyZeroArray, sizeof (NCollection_Mat4));
224 //! Checks the matrix for zero (without tolerance).
227 return std::memcmp (this, MyZeroArray, sizeof (NCollection_Mat4)) == 0;
230 //! Initialize the identity matrix.
233 std::memcpy (this, MyIdentityArray, sizeof (NCollection_Mat4));
236 //! Checks the matrix for identity (without tolerance).
237 bool IsIdentity() const
239 return std::memcmp (this, MyIdentityArray, sizeof (NCollection_Mat4)) == 0;
242 //! Check this matrix for equality with another matrix (without tolerance!).
243 bool IsEqual (const NCollection_Mat4& theOther) const
245 return std::memcmp (this, &theOther, sizeof(NCollection_Mat4)) == 0;
248 //! Check this matrix for equality with another matrix (without tolerance!).
249 bool operator== (const NCollection_Mat4& theOther) const { return IsEqual (theOther); }
251 //! Check this matrix for non-equality with another matrix (without tolerance!).
252 bool operator!= (const NCollection_Mat4& theOther) const { return !IsEqual (theOther); }
254 //! Raw access to the data (for OpenGL exchange);
255 //! the data is returned in column-major order.
256 const Element_t* GetData() const { return myMat; }
257 Element_t* ChangeData() { return myMat; }
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
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());
270 //! Compute matrix multiplication product: A * B.
271 //! @param theMatA [in] the matrix "A".
272 //! @param theMatB [in] the matrix "B".
273 static NCollection_Mat4 Multiply (const NCollection_Mat4& theMatA,
274 const NCollection_Mat4& theMatB)
276 NCollection_Mat4 aMatRes;
279 for (size_t aResElem = 0; aResElem < 16; ++aResElem)
281 aMatRes.myMat[aResElem] = (Element_t )0;
282 for (aInputElem = 0; aInputElem < 4; ++aInputElem)
284 aMatRes.myMat[aResElem] += theMatA.GetValue(aResElem % 4, aInputElem)
285 * theMatB.GetValue(aInputElem, aResElem / 4);
292 //! Compute matrix multiplication.
293 //! @param theMat [in] the matrix to multiply.
294 void Multiply (const NCollection_Mat4& theMat)
296 *this = Multiply(*this, theMat);
299 //! Multiply by the another matrix.
300 //! @param theMat [in] the other matrix.
301 NCollection_Mat4& operator*= (const NCollection_Mat4& theMat)
307 //! Compute matrix multiplication product.
308 //! @param theMat [in] the other matrix.
309 //! @return result of multiplication.
310 Standard_NODISCARD NCollection_Mat4 operator* (const NCollection_Mat4& theMat) const
312 return Multiplied (theMat);
315 //! Compute matrix multiplication product.
316 //! @param theMat [in] the other matrix.
317 //! @return result of multiplication.
318 Standard_NODISCARD NCollection_Mat4 Multiplied (const NCollection_Mat4& theMat) const
320 NCollection_Mat4 aTempMat (*this);
325 //! Compute per-component multiplication.
326 //! @param theFactor [in] the scale factor.
327 void Multiply (const Element_t theFactor)
329 for (size_t i = 0; i < 16; ++i)
331 myMat[i] *= theFactor;
335 //! Compute per-element multiplication.
336 //! @param theFactor [in] the scale factor.
337 NCollection_Mat4& operator*= (const Element_t theFactor)
339 Multiply (theFactor);
343 //! Compute per-element multiplication.
344 //! @param theFactor [in] the scale factor.
345 //! @return the result of multiplication.
346 Standard_NODISCARD NCollection_Mat4 operator* (const Element_t theFactor) const
348 return Multiplied (theFactor);
351 //! Compute per-element multiplication.
352 //! @param theFactor [in] the scale factor.
353 //! @return the result of multiplication.
354 Standard_NODISCARD NCollection_Mat4 Multiplied (const Element_t theFactor) const
356 NCollection_Mat4 aTempMat (*this);
357 aTempMat *= theFactor;
361 //! Compute per-component division.
362 //! @param theFactor [in] the scale factor.
363 void Divide (const Element_t theFactor)
365 for (size_t i = 0; i < 16; ++i)
367 myMat[i] /= theFactor;
371 //! Per-component division.
372 //! @param theScalar [in] the scale factor.
373 NCollection_Mat4& operator/= (const Element_t theScalar)
379 //! Divides all the coefficients of the matrix by scalar.
380 Standard_NODISCARD NCollection_Mat4 Divided (const Element_t theScalar) const
382 NCollection_Mat4 aTempMat (*this);
383 aTempMat /= theScalar;
387 //! Divides all the coefficients of the matrix by scalar.
388 Standard_NODISCARD NCollection_Mat4 operator/ (const Element_t theScalar) const
390 return Divided (theScalar);
393 //! Per-component addition of another matrix.
394 void Add (const NCollection_Mat4& theMat)
396 for (size_t i = 0; i < 16; ++i)
398 myMat[i] += theMat.myMat[i];
402 //! Per-component addition of another matrix.
403 NCollection_Mat4& operator+= (const NCollection_Mat4& theMat)
409 //! Per-component subtraction of another matrix.
410 void Subtract (const NCollection_Mat4& theMat)
412 for (size_t i = 0; i < 16; ++i)
414 myMat[i] -= theMat.myMat[i];
418 //! Per-component subtraction of another matrix.
419 NCollection_Mat4& operator-= (const NCollection_Mat4& theMat)
425 //! Per-component addition of another matrix.
426 Standard_NODISCARD NCollection_Mat4 Added (const NCollection_Mat4& theMat) const
428 NCollection_Mat4 aMat (*this);
433 //! Per-component addition of another matrix.
434 Standard_NODISCARD NCollection_Mat4 operator+ (const NCollection_Mat4& theMat) const { return Added (theMat); }
436 //! Per-component subtraction of another matrix.
437 Standard_NODISCARD NCollection_Mat4 Subtracted (const NCollection_Mat4& theMat) const
439 NCollection_Mat4 aMat (*this);
444 //! Per-component subtraction of another matrix.
445 Standard_NODISCARD NCollection_Mat4 operator- (const NCollection_Mat4& theMat) const { return Subtracted (theMat); }
447 //! Returns matrix with all components negated.
448 Standard_NODISCARD NCollection_Mat4 Negated() const
450 NCollection_Mat4 aMat;
451 for (size_t i = 0; i < 16; ++i)
453 aMat.myMat[i] = -myMat[i];
458 //! Returns matrix with all components negated.
459 Standard_NODISCARD NCollection_Mat4 operator-() const { return Negated(); }
461 //! Translate the matrix on the passed vector.
462 //! @param theVec [in] the translation vector.
463 void Translate (const NCollection_Vec3<Element_t>& theVec)
465 NCollection_Mat4 aTempMat;
466 aTempMat.SetColumn (3, theVec);
467 this->Multiply (aTempMat);
470 //! Transpose the matrix.
471 //! @return transposed copy of the matrix.
472 Standard_NODISCARD NCollection_Mat4 Transposed() const
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));
482 //! Transpose the matrix.
485 *this = Transposed();
488 //! Compute inverted matrix.
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
494 Element_t* inv = theOutMx.myMat;
496 // use short-cut for better readability
497 const Element_t* m = myMat;
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
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]);
563 theDet = m[0] * inv[ 0] +
572 const Element_t aDiv = (Element_t) 1. / theDet;
573 for (int i = 0; i < 16; ++i)
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
586 return Inverted (theOutMx, aDet);
589 //! Return inverted matrix.
590 NCollection_Mat4 Inverted() const
592 NCollection_Mat4 anInv;
593 if (!Inverted (anInv))
595 throw Standard_ConstructionError ("NCollection_Mat4::Inverted() - matrix has zero determinant");
600 //! Return determinant of the 3x3 sub-matrix.
601 Element_t DeterminantMat3() const
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));
611 //! Return adjoint (adjugate matrix, e.g. conjugate transpose).
612 Standard_NODISCARD NCollection_Mat4<Element_t> Adjoint() const
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)));
622 //! Take values from NCollection_Mat4 with a different element type with type conversion.
623 template <typename Other_t>
624 void ConvertFrom (const NCollection_Mat4<Other_t>& theFrom)
626 for (int anIdx = 0; anIdx < 16; ++anIdx)
628 myMat[anIdx] = static_cast<Element_t> (theFrom.myMat[anIdx]);
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); }
636 //! Maps plain C array to matrix type.
637 static NCollection_Mat4<Element_t>& Map (Element_t* theData)
639 return *reinterpret_cast<NCollection_Mat4<Element_t>*> (theData);
642 //! Maps plain C array to matrix type.
643 static const NCollection_Mat4<Element_t>& Map (const Element_t* theData)
645 return *reinterpret_cast<const NCollection_Mat4<Element_t>*> (theData);
648 //! Dumps the content of me into the stream
649 void DumpJson (Standard_OStream& theOStream, Standard_Integer) const
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))
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)
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());
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;
686 static const Element_t MyZeroArray[16];
687 static const Element_t MyIdentityArray[16];
689 // All instantiations are friend to each other
690 template<class OtherType> friend class NCollection_Mat4;
694 template<typename Element_t>
695 const Element_t NCollection_Mat4<Element_t>::MyZeroArray[] =
701 template<typename Element_t>
702 const Element_t NCollection_Mat4<Element_t>::MyIdentityArray[] =
708 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
709 #include <type_traits>
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!");
713 static_assert(sizeof(NCollection_Mat4<float>) == sizeof(float)*16, "NCollection_Mat4 is not packed/aligned!");
716 #endif // _NCollection_Mat4_HeaderFile