Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-18 09:21:15

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