Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2024-11-15 09:47:44

0001 // Created on: 2013-05-30
0002 // Created by: Anton POLETAEV
0003 // Copyright (c) 2013-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _NCollection_Mat4_HeaderFile
0017 #define _NCollection_Mat4_HeaderFile
0018 
0019 #include <NCollection_Vec4.hxx>
0020 #include <NCollection_Mat3.hxx>
0021 
0022 //! Generic matrix of 4 x 4 elements.
0023 //! To be used in conjunction with NCollection_Vec4 entities.
0024 //! Originally introduced for 3D space projection and orientation operations.
0025 //! Warning, empty constructor returns an identity matrix.
0026 template<typename Element_t>
0027 class NCollection_Mat4
0028 {
0029 public:
0030 
0031   //! Get number of rows.
0032   //! @return number of rows.
0033   static size_t Rows()
0034   {
0035     return 4;
0036   }
0037 
0038   //! Get number of columns.
0039   //! @retur number of columns.
0040   static size_t Cols()
0041   {
0042     return 4;
0043   }
0044 
0045   //! Return identity matrix.
0046   static NCollection_Mat4 Identity()
0047   {
0048     return NCollection_Mat4();
0049   }
0050 
0051   //! Return zero matrix.
0052   static NCollection_Mat4 Zero()
0053   {
0054     NCollection_Mat4 aMat; aMat.InitZero();
0055     return aMat;
0056   }
0057 
0058 public:
0059 
0060   //! Empty constructor.
0061   //! Construct the identity matrix.
0062   NCollection_Mat4()
0063   {
0064     InitIdentity();
0065   }
0066 
0067   //! Conversion constructor (explicitly converts some 4 x 4 matrix with other element type
0068   //! to a new 4 x 4 matrix with the element type Element_t,
0069   //! whose elements are static_cast'ed corresponding elements of theOtherMat4 matrix)
0070   //! @tparam OtherElement_t the element type of the other 4 x 4 matrix theOtherVec4
0071   //! @param theOtherMat4 the 4 x 4 matrix that needs to be converted
0072   template <typename OtherElement_t>
0073   explicit NCollection_Mat4 (const NCollection_Mat4<OtherElement_t>& theOtherMat4)
0074   {
0075     ConvertFrom (theOtherMat4);
0076   }
0077 
0078   //! Get element at the specified row and column.
0079   //! @param theRow [in] the row to address.
0080   //! @param theCol [in] the column to address.
0081   //! @return the value of the addressed element.
0082   Element_t GetValue (const size_t theRow, const size_t theCol) const
0083   {
0084     return myMat[theCol * 4 + theRow];
0085   }
0086 
0087   //! Access element at the specified row and column.
0088   //! @param theRow [in] the row to access.
0089   //! @param theCol [in] the column to access.
0090   //! @return reference on the matrix element.
0091   Element_t& ChangeValue (const size_t theRow, const size_t theCol)
0092   {
0093     return myMat[theCol * 4 + theRow];
0094   }
0095 
0096   //! Set value for the element specified by row and columns.
0097   //! @param theRow   [in] the row to change.
0098   //! @param theCol   [in] the column to change.
0099   //! @param theValue [in] the value to set.
0100   void SetValue (const size_t    theRow,
0101                  const size_t    theCol,
0102                  const Element_t theValue)
0103   {
0104     myMat[theCol * 4 + theRow] = theValue;
0105   }
0106 
0107   //! Return value.
0108   Element_t& operator() (const size_t theRow, const size_t theCol) { return ChangeValue (theRow, theCol); }
0109 
0110   //! Return value.
0111   Element_t  operator() (const size_t theRow, const size_t theCol) const { return GetValue (theRow, theCol); }
0112 
0113   //! Get vector of elements for the specified row.
0114   //! @param theRow [in] the row to access.
0115   //! @return vector of elements.
0116   NCollection_Vec4<Element_t> GetRow (const size_t theRow) const
0117   {
0118     return NCollection_Vec4<Element_t> (GetValue (theRow, 0),
0119                                         GetValue (theRow, 1),
0120                                         GetValue (theRow, 2),
0121                                         GetValue (theRow, 3));
0122   }
0123 
0124   //! Change first 3 row values by the passed vector.
0125   //! @param theRow [in] the row to change.
0126   //! @param theVec [in] the vector of values.
0127   void SetRow (const size_t theRow, const NCollection_Vec3<Element_t>& theVec)
0128   {
0129     SetValue (theRow, 0, theVec.x());
0130     SetValue (theRow, 1, theVec.y());
0131     SetValue (theRow, 2, theVec.z());
0132   }
0133 
0134   //! Set row values by the passed 4 element vector.
0135   //! @param theRow [in] the row to change.
0136   //! @param theVec [in] the vector of values.
0137   void SetRow (const size_t theRow, const NCollection_Vec4<Element_t>& theVec)
0138   {
0139     SetValue (theRow, 0, theVec.x());
0140     SetValue (theRow, 1, theVec.y());
0141     SetValue (theRow, 2, theVec.z());
0142     SetValue (theRow, 3, theVec.w());
0143   }
0144 
0145   //! Get vector of elements for the specified column.
0146   //! @param theCol [in] the column to access.
0147   //! @return vector of elements.
0148   NCollection_Vec4<Element_t> GetColumn (const size_t theCol) const
0149   {
0150     return NCollection_Vec4<Element_t> (GetValue (0, theCol),
0151                                         GetValue (1, theCol),
0152                                         GetValue (2, theCol),
0153                                         GetValue (3, theCol));
0154   }
0155 
0156   //! Change first 3 column values by the passed vector.
0157   //! @param theCol [in] the column to change.
0158   //! @param theVec [in] the vector of values.
0159   void SetColumn (const size_t theCol,
0160                   const NCollection_Vec3<Element_t>& theVec)
0161   {
0162     SetValue (0, theCol, theVec.x());
0163     SetValue (1, theCol, theVec.y());
0164     SetValue (2, theCol, theVec.z());
0165   }
0166 
0167   //! Set column values by the passed 4 element vector.
0168   //! @param theCol [in] the column to change.
0169   //! @param theVec [in] the vector of values.
0170   void SetColumn (const size_t theCol,
0171                   const NCollection_Vec4<Element_t>& theVec)
0172   {
0173     SetValue (0, theCol, theVec.x());
0174     SetValue (1, theCol, theVec.y());
0175     SetValue (2, theCol, theVec.z());
0176     SetValue (3, theCol, theVec.w());
0177   }
0178 
0179   //! Get vector of diagonal elements.
0180   //! @return vector of diagonal elements.
0181   NCollection_Vec4<Element_t> GetDiagonal() const
0182   {
0183     return NCollection_Vec4<Element_t> (GetValue (0, 0),
0184                                         GetValue (1, 1),
0185                                         GetValue (2, 2),
0186                                         GetValue (3, 3));
0187   }
0188 
0189   //! Change first 3 elements of the diagonal matrix.
0190   //! @param theVec the vector of values.
0191   void SetDiagonal (const NCollection_Vec3<Element_t>& theVec)
0192   {
0193     SetValue (0, 0, theVec.x());
0194     SetValue (1, 1, theVec.y());
0195     SetValue (2, 2, theVec.z());
0196   }
0197 
0198   //! Set diagonal elements of the matrix by the passed vector.
0199   //! @param theVec [in] the vector of values.
0200   void SetDiagonal (const NCollection_Vec4<Element_t>& theVec)
0201   {
0202     SetValue (0, 0, theVec.x());
0203     SetValue (1, 1, theVec.y());
0204     SetValue (2, 2, theVec.z());
0205     SetValue (3, 3, theVec.w());
0206   }
0207 
0208   //! Return 3x3 sub-matrix.
0209   NCollection_Mat3<Element_t> GetMat3() const
0210   {
0211     NCollection_Mat3<Element_t> aMat;
0212     aMat.SetColumn (0, GetColumn (0).xyz());
0213     aMat.SetColumn (1, GetColumn (1).xyz());
0214     aMat.SetColumn (2, GetColumn (2).xyz());
0215     return aMat;
0216   }
0217 
0218   //! Initialize the zero matrix.
0219   void InitZero()
0220   {
0221     std::memcpy (this, MyZeroArray, sizeof (NCollection_Mat4));
0222   }
0223 
0224   //! Checks the matrix for zero (without tolerance).
0225   bool IsZero() const
0226   {
0227     return std::memcmp (this, MyZeroArray, sizeof (NCollection_Mat4)) == 0;
0228   }
0229 
0230   //! Initialize the identity matrix.
0231   void InitIdentity()
0232   {
0233     std::memcpy (this, MyIdentityArray, sizeof (NCollection_Mat4));
0234   }
0235 
0236   //! Checks the matrix for identity (without tolerance).
0237   bool IsIdentity() const
0238   {
0239     return std::memcmp (this, MyIdentityArray, sizeof (NCollection_Mat4)) == 0;
0240   }
0241 
0242   //! Check this matrix for equality with another matrix (without tolerance!).
0243   bool IsEqual (const NCollection_Mat4& theOther) const
0244   {
0245     return std::memcmp (this, &theOther, sizeof(NCollection_Mat4)) == 0;
0246   }
0247 
0248   //! Check this matrix for equality with another matrix (without tolerance!).
0249   bool operator== (const NCollection_Mat4& theOther) const { return IsEqual (theOther); }
0250 
0251   //! Check this matrix for non-equality with another matrix (without tolerance!).
0252   bool operator!= (const NCollection_Mat4& theOther) const { return !IsEqual (theOther); }
0253 
0254   //! Raw access to the data (for OpenGL exchange);
0255   //! the data is returned in column-major order.
0256   const Element_t* GetData()    const { return myMat; }
0257   Element_t*       ChangeData()       { return myMat; }
0258 
0259   //! Multiply by the vector (M * V).
0260   //! @param theVec [in] the vector to multiply.
0261   NCollection_Vec4<Element_t> operator* (const NCollection_Vec4<Element_t>& theVec) const
0262   {
0263     return NCollection_Vec4<Element_t> (
0264       GetValue (0, 0) * theVec.x() + GetValue (0, 1) * theVec.y() + GetValue (0, 2) * theVec.z() + GetValue (0, 3) * theVec.w(),
0265       GetValue (1, 0) * theVec.x() + GetValue (1, 1) * theVec.y() + GetValue (1, 2) * theVec.z() + GetValue (1, 3) * theVec.w(),
0266       GetValue (2, 0) * theVec.x() + GetValue (2, 1) * theVec.y() + GetValue (2, 2) * theVec.z() + GetValue (2, 3) * theVec.w(),
0267       GetValue (3, 0) * theVec.x() + GetValue (3, 1) * theVec.y() + GetValue (3, 2) * theVec.z() + GetValue (3, 3) * theVec.w());
0268   }
0269 
0270   //! Compute matrix multiplication product: A * B.
0271   //! @param theMatA [in] the matrix "A".
0272   //! @param theMatB [in] the matrix "B".
0273   static NCollection_Mat4 Multiply (const NCollection_Mat4& theMatA,
0274                                     const NCollection_Mat4& theMatB)
0275   {
0276     NCollection_Mat4 aMatRes;
0277 
0278     size_t aInputElem;
0279     for (size_t aResElem = 0; aResElem < 16; ++aResElem)
0280     {
0281       aMatRes.myMat[aResElem] = (Element_t )0;
0282       for (aInputElem = 0; aInputElem < 4; ++aInputElem)
0283       {
0284         aMatRes.myMat[aResElem] += theMatA.GetValue(aResElem % 4, aInputElem)
0285                                  * theMatB.GetValue(aInputElem, aResElem / 4);
0286       }
0287     }
0288 
0289     return aMatRes;
0290   }
0291 
0292   //! Compute matrix multiplication.
0293   //! @param theMat [in] the matrix to multiply.
0294   void Multiply (const NCollection_Mat4& theMat)
0295   {
0296     *this = Multiply(*this, theMat);
0297   }
0298 
0299   //! Multiply by the another matrix.
0300   //! @param theMat [in] the other matrix.
0301   NCollection_Mat4& operator*= (const NCollection_Mat4& theMat)
0302   {
0303     Multiply (theMat);
0304     return *this;
0305   }
0306 
0307   //! Compute matrix multiplication product.
0308   //! @param theMat [in] the other matrix.
0309   //! @return result of multiplication.
0310   Standard_NODISCARD NCollection_Mat4 operator* (const NCollection_Mat4& theMat) const
0311   {
0312     return Multiplied (theMat);
0313   }
0314 
0315   //! Compute matrix multiplication product.
0316   //! @param theMat [in] the other matrix.
0317   //! @return result of multiplication.
0318   Standard_NODISCARD NCollection_Mat4 Multiplied (const NCollection_Mat4& theMat) const
0319   {
0320     NCollection_Mat4 aTempMat (*this);
0321     aTempMat *= theMat;
0322     return aTempMat;
0323   }
0324 
0325   //! Compute per-component multiplication.
0326   //! @param theFactor [in] the scale factor.
0327   void Multiply (const Element_t theFactor)
0328   {
0329     for (size_t i = 0; i < 16; ++i)
0330     {
0331       myMat[i] *= theFactor;
0332     }
0333   }
0334 
0335   //! Compute per-element multiplication.
0336   //! @param theFactor [in] the scale factor.
0337   NCollection_Mat4& operator*= (const Element_t theFactor)
0338   {
0339     Multiply (theFactor);
0340     return *this;
0341   }
0342 
0343   //! Compute per-element multiplication.
0344   //! @param theFactor [in] the scale factor.
0345   //! @return the result of multiplication.
0346   Standard_NODISCARD NCollection_Mat4 operator* (const Element_t theFactor) const
0347   {
0348     return Multiplied (theFactor);
0349   }
0350 
0351   //! Compute per-element multiplication.
0352   //! @param theFactor [in] the scale factor.
0353   //! @return the result of multiplication.
0354   Standard_NODISCARD NCollection_Mat4 Multiplied (const Element_t theFactor) const
0355   {
0356     NCollection_Mat4 aTempMat (*this);
0357     aTempMat *= theFactor;
0358     return aTempMat;
0359   }
0360 
0361   //! Compute per-component division.
0362   //! @param theFactor [in] the scale factor.
0363   void Divide (const Element_t theFactor)
0364   {
0365     for (size_t i = 0; i < 16; ++i)
0366     {
0367       myMat[i] /= theFactor;
0368     }
0369   }
0370 
0371   //! Per-component division.
0372   //! @param theScalar [in] the scale factor.
0373   NCollection_Mat4& operator/= (const Element_t theScalar)
0374   {
0375     Divide (theScalar);
0376     return *this;
0377   }
0378 
0379   //! Divides all the coefficients of the matrix by scalar.
0380   Standard_NODISCARD NCollection_Mat4 Divided (const Element_t theScalar) const
0381   {
0382     NCollection_Mat4 aTempMat (*this);
0383     aTempMat /= theScalar;
0384     return aTempMat;
0385   }
0386 
0387   //! Divides all the coefficients of the matrix by scalar.
0388   Standard_NODISCARD NCollection_Mat4 operator/ (const Element_t theScalar) const
0389   {
0390     return Divided (theScalar);
0391   }
0392 
0393   //! Per-component addition of another matrix.
0394   void Add (const NCollection_Mat4& theMat)
0395   {
0396     for (size_t i = 0; i < 16; ++i)
0397     {
0398       myMat[i] += theMat.myMat[i];
0399     }
0400   }
0401 
0402   //! Per-component addition of another matrix.
0403   NCollection_Mat4& operator+= (const NCollection_Mat4& theMat)
0404   {
0405     Add (theMat);
0406     return *this;
0407   }
0408 
0409   //! Per-component subtraction of another matrix.
0410   void Subtract (const NCollection_Mat4& theMat)
0411   {
0412     for (size_t i = 0; i < 16; ++i)
0413     {
0414       myMat[i] -= theMat.myMat[i];
0415     }
0416   }
0417 
0418   //! Per-component subtraction of another matrix.
0419   NCollection_Mat4& operator-= (const NCollection_Mat4& theMat)
0420   {
0421     Subtract (theMat);
0422     return *this;
0423   }
0424 
0425   //! Per-component addition of another matrix.
0426   Standard_NODISCARD NCollection_Mat4 Added (const NCollection_Mat4& theMat) const
0427   {
0428     NCollection_Mat4 aMat (*this);
0429     aMat += theMat;
0430     return aMat;
0431   }
0432 
0433   //! Per-component addition of another matrix.
0434   Standard_NODISCARD NCollection_Mat4 operator+ (const NCollection_Mat4& theMat) const { return Added (theMat); }
0435 
0436   //! Per-component subtraction of another matrix.
0437   Standard_NODISCARD NCollection_Mat4 Subtracted (const NCollection_Mat4& theMat) const
0438   {
0439     NCollection_Mat4 aMat (*this);
0440     aMat -= theMat;
0441     return aMat;
0442   }
0443 
0444   //! Per-component subtraction of another matrix.
0445   Standard_NODISCARD NCollection_Mat4 operator- (const NCollection_Mat4& theMat) const { return Subtracted (theMat); }
0446 
0447   //! Returns matrix with all components negated.
0448   Standard_NODISCARD NCollection_Mat4 Negated() const
0449   {
0450     NCollection_Mat4 aMat;
0451     for (size_t i = 0; i < 16; ++i)
0452     {
0453       aMat.myMat[i] = -myMat[i];
0454     }
0455     return aMat;
0456   }
0457 
0458   //! Returns matrix with all components negated.
0459   Standard_NODISCARD NCollection_Mat4 operator-() const { return Negated(); }
0460 
0461   //! Translate the matrix on the passed vector.
0462   //! @param theVec [in] the translation vector.
0463   void Translate (const NCollection_Vec3<Element_t>& theVec)
0464   {
0465     NCollection_Mat4 aTempMat;
0466     aTempMat.SetColumn (3, theVec);
0467     this->Multiply (aTempMat);
0468   }
0469 
0470   //! Transpose the matrix.
0471   //! @return transposed copy of the matrix.
0472   Standard_NODISCARD NCollection_Mat4 Transposed() const
0473   {
0474     NCollection_Mat4 aTempMat;
0475     aTempMat.SetRow (0, GetColumn (0));
0476     aTempMat.SetRow (1, GetColumn (1));
0477     aTempMat.SetRow (2, GetColumn (2));
0478     aTempMat.SetRow (3, GetColumn (3));
0479     return aTempMat;
0480   }
0481 
0482   //! Transpose the matrix.
0483   void Transpose()
0484   {
0485     *this = Transposed();
0486   }
0487 
0488   //! Compute inverted matrix.
0489   //! @param theOutMx [out] the inverted matrix
0490   //! @param theDet   [out] determinant of matrix
0491   //! @return true if reversion success
0492   bool Inverted (NCollection_Mat4<Element_t>& theOutMx, Element_t& theDet) const
0493   {
0494     Element_t* inv = theOutMx.myMat;
0495 
0496     // use short-cut for better readability
0497     const Element_t* m = myMat;
0498 
0499     inv[ 0] = m[ 5] * (m[10] * m[15] - m[11] * m[14]) -
0500               m[ 9] * (m[ 6] * m[15] - m[ 7] * m[14]) -
0501               m[13] * (m[ 7] * m[10] - m[ 6] * m[11]);
0502 
0503     inv[ 1] = m[ 1] * (m[11] * m[14] - m[10] * m[15]) -
0504               m[ 9] * (m[ 3] * m[14] - m[ 2] * m[15]) -
0505               m[13] * (m[ 2] * m[11] - m[ 3] * m[10]);
0506 
0507     inv[ 2] = m[ 1] * (m[ 6] * m[15] - m[ 7] * m[14]) -
0508               m[ 5] * (m[ 2] * m[15] - m[ 3] * m[14]) -
0509               m[13] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
0510 
0511     inv[ 3] = m[ 1] * (m[ 7] * m[10] - m[ 6] * m[11]) -
0512               m[ 5] * (m[ 3] * m[10] - m[ 2] * m[11]) -
0513               m[ 9] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
0514 
0515     inv[ 4] = m[ 4] * (m[11] * m[14] - m[10] * m[15]) -
0516               m[ 8] * (m[ 7] * m[14] - m[ 6] * m[15]) -
0517               m[12] * (m[ 6] * m[11] - m[ 7] * m[10]);
0518 
0519     inv[ 5] = m[ 0] * (m[10] * m[15] - m[11] * m[14]) -
0520               m[ 8] * (m[ 2] * m[15] - m[ 3] * m[14]) -
0521               m[12] * (m[ 3] * m[10] - m[ 2] * m[11]);
0522 
0523     inv[ 6] = m[ 0] * (m[ 7] * m[14] - m[ 6] * m[15]) -
0524               m[ 4] * (m[ 3] * m[14] - m[ 2] * m[15]) -
0525               m[12] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
0526 
0527     inv[ 7] = m[ 0] * (m[ 6] * m[11] - m[ 7] * m[10]) -
0528               m[ 4] * (m[ 2] * m[11] - m[ 3] * m[10]) -
0529               m[ 8] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
0530 
0531     inv[ 8] = m[ 4] * (m[ 9] * m[15] - m[11] * m[13]) -
0532               m[ 8] * (m[ 5] * m[15] - m[ 7] * m[13]) -
0533               m[12] * (m[ 7] * m[ 9] - m[ 5] * m[11]);
0534 
0535     inv[ 9] = m[ 0] * (m[11] * m[13] - m[ 9] * m[15]) -
0536               m[ 8] * (m[ 3] * m[13] - m[ 1] * m[15]) -
0537               m[12] * (m[ 1] * m[11] - m[ 3] * m[ 9]);
0538 
0539     inv[10] = m[ 0] * (m[ 5] * m[15] - m[ 7] * m[13]) -
0540               m[ 4] * (m[ 1] * m[15] - m[ 3] * m[13]) -
0541               m[12] * (m[ 3] * m[ 5] - m[ 1] * m[ 7]);
0542 
0543     inv[11] = m[ 0] * (m[ 7] * m[ 9] - m[ 5] * m[11]) -
0544               m[ 4] * (m[ 3] * m[ 9] - m[ 1] * m[11]) -
0545               m[ 8] * (m[ 1] * m[ 7] - m[ 3] * m[ 5]);
0546 
0547     inv[12] = m[ 4] * (m[10] * m[13] - m[ 9] * m[14]) -
0548               m[ 8] * (m[ 6] * m[13] - m[ 5] * m[14]) -
0549               m[12] * (m[ 5] * m[10] - m[ 6] * m[ 9]);
0550 
0551     inv[13] = m[ 0] * (m[ 9] * m[14] - m[10] * m[13]) -
0552               m[ 8] * (m[ 1] * m[14] - m[ 2] * m[13]) -
0553               m[12] * (m[ 2] * m[ 9] - m[ 1] * m[10]);
0554 
0555     inv[14] = m[ 0] * (m[ 6] * m[13] - m[ 5] * m[14]) -
0556               m[ 4] * (m[ 2] * m[13] - m[ 1] * m[14]) -
0557               m[12] * (m[ 1] * m[ 6] - m[ 2] * m[ 5]);
0558 
0559     inv[15] = m[ 0] * (m[ 5] * m[10] - m[ 6] * m[ 9]) -
0560               m[ 4] * (m[ 1] * m[10] - m[ 2] * m[ 9]) -
0561               m[ 8] * (m[ 2] * m[ 5] - m[ 1] * m[ 6]);
0562 
0563     theDet = m[0] * inv[ 0] +
0564              m[1] * inv[ 4] +
0565              m[2] * inv[ 8] +
0566              m[3] * inv[12];
0567     if (theDet == 0)
0568     {
0569       return false;
0570     }
0571 
0572     const Element_t aDiv = (Element_t) 1. / theDet;
0573     for (int i = 0; i < 16; ++i)
0574     {
0575       inv[i] *= aDiv;
0576     }
0577     return true;
0578   }
0579 
0580   //! Compute inverted matrix.
0581   //! @param theOutMx [out] the inverted matrix
0582   //! @return true if reversion success
0583   bool Inverted (NCollection_Mat4<Element_t>& theOutMx) const
0584   {
0585     Element_t aDet;
0586     return Inverted (theOutMx, aDet);
0587   }
0588 
0589   //! Return inverted matrix.
0590   NCollection_Mat4 Inverted() const
0591   {
0592     NCollection_Mat4 anInv;
0593     if (!Inverted (anInv))
0594     {
0595       throw Standard_ConstructionError ("NCollection_Mat4::Inverted() - matrix has zero determinant");
0596     }
0597     return anInv;
0598   }
0599 
0600   //! Return determinant of the 3x3 sub-matrix.
0601   Element_t DeterminantMat3() const
0602   {
0603     return (GetValue (0, 0) * GetValue (1, 1) * GetValue (2, 2)
0604           + GetValue (0, 1) * GetValue (1, 2) * GetValue (2, 0)
0605           + GetValue (0, 2) * GetValue (1, 0) * GetValue (2, 1))
0606          - (GetValue (0, 2) * GetValue (1, 1) * GetValue (2, 0)
0607           + GetValue (0, 0) * GetValue (1, 2) * GetValue (2, 1)
0608           + GetValue (0, 1) * GetValue (1, 0) * GetValue (2, 2));
0609   }
0610 
0611   //! Return adjoint (adjugate matrix, e.g. conjugate transpose).
0612   Standard_NODISCARD NCollection_Mat4<Element_t> Adjoint() const
0613   {
0614     NCollection_Mat4<Element_t> aMat;
0615     aMat.SetRow (0, crossVec4 ( GetRow (1), GetRow (2), GetRow (3)));
0616     aMat.SetRow (1, crossVec4 (-GetRow (0), GetRow (2), GetRow (3)));
0617     aMat.SetRow (2, crossVec4 ( GetRow (0), GetRow (1), GetRow (3)));
0618     aMat.SetRow (3, crossVec4 (-GetRow (0), GetRow (1), GetRow (2)));
0619     return aMat;
0620   }
0621 
0622   //! Take values from NCollection_Mat4 with a different element type with type conversion.
0623   template <typename Other_t>
0624   void ConvertFrom (const NCollection_Mat4<Other_t>& theFrom)
0625   {
0626     for (int anIdx = 0; anIdx < 16; ++anIdx)
0627     {
0628       myMat[anIdx] = static_cast<Element_t> (theFrom.myMat[anIdx]);
0629     }
0630   }
0631 
0632   //! Take values from NCollection_Mat4 with a different element type with type conversion.
0633   template <typename Other_t>
0634   void Convert (const NCollection_Mat4<Other_t>& theFrom) { ConvertFrom (theFrom); }
0635 
0636   //! Maps plain C array to matrix type.
0637   static NCollection_Mat4<Element_t>& Map (Element_t* theData)
0638   {
0639     return *reinterpret_cast<NCollection_Mat4<Element_t>*> (theData);
0640   }
0641 
0642   //! Maps plain C array to matrix type.
0643   static const NCollection_Mat4<Element_t>& Map (const Element_t* theData)
0644   {
0645     return *reinterpret_cast<const NCollection_Mat4<Element_t>*> (theData);
0646   }
0647 
0648   //! Dumps the content of me into the stream
0649   void DumpJson (Standard_OStream& theOStream, Standard_Integer) const
0650   {
0651     OCCT_DUMP_FIELD_VALUES_NUMERICAL (theOStream, "NCollection_Mat4", 16,
0652       GetValue (0, 0),  GetValue (0, 1), GetValue (0, 2),  GetValue (0, 3),
0653       GetValue (1, 0),  GetValue (1, 1), GetValue (1, 2),  GetValue (1, 3),
0654       GetValue (2, 0),  GetValue (2, 1), GetValue (2, 2),  GetValue (2, 3),
0655       GetValue (3, 0),  GetValue (3, 1), GetValue (3, 2),  GetValue (3, 3))
0656   }
0657 
0658 private:
0659 
0660   //! Cross-product has no direct meaning in 4D space - provided for local usage.
0661   static NCollection_Vec4<Element_t> crossVec4 (const NCollection_Vec4<Element_t>& theA,
0662                                                 const NCollection_Vec4<Element_t>& theB,
0663                                                 const NCollection_Vec4<Element_t>& theC)
0664   {
0665     const Element_t aD1 = (theB.z() * theC.w()) - (theB.w() * theC.z());
0666     const Element_t aD2 = (theB.y() * theC.w()) - (theB.w() * theC.y());
0667     const Element_t aD3 = (theB.y() * theC.z()) - (theB.z() * theC.y());
0668     const Element_t aD4 = (theB.x() * theC.w()) - (theB.w() * theC.x());
0669     const Element_t aD5 = (theB.x() * theC.z()) - (theB.z() * theC.x());
0670     const Element_t aD6 = (theB.x() * theC.y()) - (theB.y() * theC.x());
0671 
0672     NCollection_Vec4<Element_t> aVec;
0673     aVec.x() = -theA.y() * aD1 + theA.z() * aD2 - theA.w() * aD3;
0674     aVec.y() =  theA.x() * aD1 - theA.z() * aD4 + theA.w() * aD5;
0675     aVec.z() = -theA.x() * aD2 + theA.y() * aD4 - theA.w() * aD6;
0676     aVec.w() =  theA.x() * aD3 - theA.y() * aD5 + theA.z() * aD6;
0677     return aVec;
0678   }
0679 
0680 private:
0681 
0682   Element_t myMat[16];
0683 
0684 private:
0685 
0686   static const Element_t MyZeroArray[16];
0687   static const Element_t MyIdentityArray[16];
0688 
0689   // All instantiations are friend to each other
0690   template<class OtherType> friend class NCollection_Mat4;
0691 
0692 };
0693 
0694 template<typename Element_t>
0695 const Element_t NCollection_Mat4<Element_t>::MyZeroArray[] =
0696   {0, 0, 0, 0,
0697    0, 0, 0, 0,
0698    0, 0, 0, 0,
0699    0, 0, 0, 0};
0700 
0701 template<typename Element_t>
0702 const Element_t NCollection_Mat4<Element_t>::MyIdentityArray[] =
0703   {1, 0, 0, 0,
0704    0, 1, 0, 0,
0705    0, 0, 1, 0,
0706    0, 0, 0, 1};
0707 
0708 #if defined(_MSC_VER) && (_MSC_VER >= 1900)
0709   #include <type_traits>
0710 
0711   static_assert(std::is_trivially_copyable<NCollection_Mat4<float>>::value, "NCollection_Mat4 is not is_trivially_copyable() structure!");
0712   static_assert(std::is_standard_layout   <NCollection_Mat4<float>>::value, "NCollection_Mat4 is not is_standard_layout() structure!");
0713   static_assert(sizeof(NCollection_Mat4<float>) == sizeof(float)*16,        "NCollection_Mat4 is not packed/aligned!");
0714 #endif
0715 
0716 #endif // _NCollection_Mat4_HeaderFile