0025617: Avoid classes with a copy constructor and the default destructor or assignme...
[occt.git] / src / NCollection / NCollection_Mat4.hxx
1 // Created on: 2013-05-30
2 // Created by: Anton POLETAEV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
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.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _NCollection_Mat4_HeaderFile
17 #define _NCollection_Mat4_HeaderFile
18
19 #include <NCollection_Vec4.hxx>
20
21 //! Generic matrix of 4 x 4 elements.
22 //! To be used in conjunction with NCollection_Vec4 entities.
23 //! Originally introduced for 3D space projection and orientation
24 //! operations.
25 template<typename Element_t>
26 class NCollection_Mat4
27 {
28
29 public:
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
45   //! Empty constructor.
46   //! Construct the zero matrix.
47   NCollection_Mat4()
48   {
49     InitIdentity();
50   }
51
52   //! Get element at the specified row and column.
53   //! @param theRow [in] the row.to address.
54   //! @param theCol [in] the column to address.
55   //! @return the value of the addressed element.
56   Element_t GetValue (const size_t theRow, const size_t theCol) const
57   {
58     return myMat[theCol * 4 + theRow];
59   }
60
61   //! Access element at the specified row and column.
62   //! @param theRow [in] the row.to access.
63   //! @param theCol [in] the column to access.
64   //! @return reference on the matrix element.
65   Element_t& ChangeValue (const size_t theRow, const size_t theCol)
66   {
67     return myMat[theCol * 4 + theRow];
68   }
69
70   //! Set value for the element specified by row and columns.
71   //! @param theRow   [in] the row to change.
72   //! @param theCol   [in] the column to change.
73   //! @param theValue [in] the value to set.s
74   void SetValue (const size_t    theRow,
75                  const size_t    theCol,
76                  const Element_t theValue)
77   {
78     myMat[theCol * 4 + theRow] = theValue;
79   }
80
81   //! Get vector of elements for the specified row.
82   //! @param theRow [in] the row to access.
83   //! @return vector of elements.
84   NCollection_Vec4<Element_t> GetRow (const size_t theRow) const
85   {
86     return NCollection_Vec4<Element_t> (GetValue (theRow, 0),
87                                         GetValue (theRow, 1),
88                                         GetValue (theRow, 2),
89                                         GetValue (theRow, 3));
90   }
91
92   //! Change first 3 row values by the passed vector.
93   //! @param theRow [in] the row to change.
94   //! @param theVec [in] the vector of values.
95   void SetRow (const size_t theRow, const NCollection_Vec3<Element_t>& theVec)
96   {
97     SetValue (theRow, 0, theVec.x());
98     SetValue (theRow, 1, theVec.y());
99     SetValue (theRow, 2, theVec.z());
100   }
101
102   //! Set row values by the passed 4 element vector.
103   //! @param theRow [in] the row to change.
104   //! @param theVec [in] the vector of values.
105   void SetRow (const size_t theRow, const NCollection_Vec4<Element_t>& theVec)
106   {
107     SetValue (theRow, 0, theVec.x());
108     SetValue (theRow, 1, theVec.y());
109     SetValue (theRow, 2, theVec.z());
110     SetValue (theRow, 3, theVec.w());
111   }
112
113   //! Get vector of elements for the specified column.
114   //! @param theCol [in] the column to access.
115   //! @return vector of elements.
116   NCollection_Vec4<Element_t> GetColumn (const size_t theCol) const
117   {
118     return NCollection_Vec4<Element_t> (GetValue (0, theCol),
119                                         GetValue (1, theCol),
120                                         GetValue (2, theCol),
121                                         GetValue (3, theCol));
122   }
123
124   //! Change first 3 column values by the passed vector.
125   //! @param theCol [in] the column to change.
126   //! @param theVec [in] the vector of values.
127   void SetColumn (const size_t theCol,
128                   const NCollection_Vec3<Element_t>& theVec)
129   {
130     SetValue (0, theCol, theVec.x());
131     SetValue (1, theCol, theVec.y());
132     SetValue (2, theCol, theVec.z());
133   }
134
135   //! Set column values by the passed 4 element vector.
136   //! @param theCol [in] the column to change.
137   //! @param theVec [in] the vector of values.
138   void SetColumn (const size_t theCol,
139                   const NCollection_Vec4<Element_t>& theVec)
140   {
141     SetValue (0, theCol, theVec.x());
142     SetValue (1, theCol, theVec.y());
143     SetValue (2, theCol, theVec.z());
144     SetValue (3, theCol, theVec.w());
145   }
146
147   //! Get vector of diagonal elements.
148   //! \return vector of diagonal elements.
149   NCollection_Vec4<Element_t> GetDiagonal() const
150   {
151     return NCollection_Vec4<Element_t> (GetValue (0, 0),
152                                         GetValue (1, 1),
153                                         GetValue (2, 2),
154                                         GetValue (3, 3));
155   }
156
157   //! Change first 3 elements of the diagonal matrix.
158   //! @param theVec the vector of values.
159   void SetDiagonal (const NCollection_Vec3<Element_t>& theVec)
160   {
161     SetValue (0, 0, theVec.x());
162     SetValue (1, 1, theVec.y());
163     SetValue (2, 2, theVec.z());
164   }
165
166   //! Set diagonal elements of the matrix by the passed vector.
167   //! @param theVec [in] the vector of values.
168   void SetDiagonal (const NCollection_Vec4<Element_t>& theVec)
169   {
170     SetValue (0, 0, theVec.x());
171     SetValue (1, 1, theVec.y());
172     SetValue (2, 2, theVec.z());
173     SetValue (3, 3, theVec.w());
174   }
175
176   //! Initialize the identity matrix.
177   void InitIdentity()
178   {
179     std::memcpy (this, myIdentityArray, sizeof (NCollection_Mat4));
180   }
181
182   //! Checks the matrix for identity.
183   bool IsIdentity() const
184   {
185     return std::memcmp (this, myIdentityArray, sizeof (NCollection_Mat4)) == 0;
186   }
187
188   //! Raw access to the data (for OpenGL exchange).
189   const Element_t* GetData()    const { return myMat; }
190   Element_t*       ChangeData()       { return myMat; }
191   operator const   Element_t*() const { return myMat; }
192   operator         Element_t*()       { return myMat; }
193
194   //! Multiply by the vector (M * V).
195   //! @param theVec [in] the vector to multiply.
196   NCollection_Vec4<Element_t> operator* (const NCollection_Vec4<Element_t>& theVec) const
197   {
198     return NCollection_Vec4<Element_t> (
199       GetValue (0, 0) * theVec.x() + GetValue (0, 1) * theVec.y() + GetValue (0, 2) * theVec.z() + GetValue (0, 3) * theVec.w(),
200       GetValue (1, 0) * theVec.x() + GetValue (1, 1) * theVec.y() + GetValue (1, 2) * theVec.z() + GetValue (1, 3) * theVec.w(),
201       GetValue (2, 0) * theVec.x() + GetValue (2, 1) * theVec.y() + GetValue (2, 2) * theVec.z() + GetValue (2, 3) * theVec.w(),
202       GetValue (3, 0) * theVec.x() + GetValue (3, 1) * theVec.y() + GetValue (3, 2) * theVec.z() + GetValue (3, 3) * theVec.w());
203   }
204
205   //! Compute matrix multiplication product: A * B.
206   //! @param theMatA [in] the matrix "A".
207   //! @param theMatB [in] the matrix "B".
208   NCollection_Mat4 Multiply (const NCollection_Mat4& theMatA,
209                              const NCollection_Mat4& theMatB)
210   {
211     NCollection_Mat4 aMatRes;
212
213     size_t aInputElem;
214     for (size_t aResElem = 0; aResElem < 16; ++aResElem)
215     {
216       aMatRes[aResElem] = (Element_t )0;
217       for (aInputElem = 0; aInputElem < 4; ++aInputElem)
218       {
219         aMatRes[aResElem] += theMatA.GetValue(aResElem % 4, aInputElem)
220                            * theMatB.GetValue(aInputElem, aResElem / 4);
221       }
222     }
223
224     return aMatRes;
225   }
226
227   //! Compute matrix multiplication.
228   //! @param theMat [in] the matrix to multiply.
229   void Multiply (const NCollection_Mat4& theMat)
230   {
231     *this = Multiply(*this, theMat);
232   }
233
234   //! Multiply by the another matrix.
235   //! @param theMat [in] the other matrix.
236   NCollection_Mat4& operator*= (const NCollection_Mat4& theMat)
237   {
238     Multiply (theMat);
239     return *this;
240   }
241
242   //! Compute matrix multiplication product.
243   //! @param theMat [in] the other matrix.
244   //! @return result of multiplication.
245   NCollection_Mat4 operator* (const NCollection_Mat4& theMat) const
246   {
247     return Multiplied (theMat);
248   }
249
250   //! Compute matrix multiplication product.
251   //! @param theMat [in] the other matrix.
252   //! @return result of multiplication.
253   NCollection_Mat4 Multiplied (const NCollection_Mat4& theMat) const
254   {
255     NCollection_Mat4 aTempMat (*this);
256     aTempMat *= theMat;
257     return aTempMat;
258   }
259
260   //! Compute per-component multiplication.
261   //! @param theFactor [in] the scale factor.
262   void Multiply (const Element_t theFactor)
263   {
264     for (size_t i = 0; i < 16; ++i)
265     {
266       myMat[i] *= theFactor;
267     }
268   }
269
270   //! Compute per-element multiplication.
271   //! @param theFactor [in] the scale factor.
272   NCollection_Mat4& operator*=(const Element_t theFactor)
273   {
274     Multiply (theFactor);
275     return *this;
276   }
277
278   //! Compute per-element multiplication.
279   //! @param theFactor [in] the scale factor.
280   //! @return the result of multiplicaton.
281   NCollection_Mat4 operator* (const Element_t theFactor) const
282   {
283     return Multiplied (theFactor);
284   }
285
286   //! Compute per-element multiplication.
287   //! @param theFactor [in] the scale factor.
288   //! @return the result of multiplicaton.
289   NCollection_Mat4 Multiplied (const Element_t theFactor) const
290   {
291     NCollection_Mat4 aTempMat (*this);
292     aTempMat *= theFactor;
293     return aTempMat;
294   }
295
296   //! Translate the matrix on the passed vector.
297   //! @param theVec [in] the translation vector.
298   void Translate (const NCollection_Vec3<Element_t>& theVec)
299   {
300     NCollection_Mat4 aTempMat;
301     aTempMat.SetColumn (3, theVec);
302     this->Multiply (aTempMat);
303   }
304
305   //! Transpose the matrix.
306   //! @return transposed copy of the matrix.
307   NCollection_Mat4 Transposed() const
308   {
309     NCollection_Mat4 aTempMat;
310     aTempMat.SetRow (0, GetColumn (0));
311     aTempMat.SetRow (1, GetColumn (1));
312     aTempMat.SetRow (2, GetColumn (2));
313     aTempMat.SetRow (3, GetColumn (3));
314     return aTempMat;
315   }
316
317   //! Transpose the matrix.
318   void Transpose()
319   {
320     *this = Transposed();
321   }
322
323   //! Compute inverted matrix.
324   //! @param theOutMx [out] the inverted matrix.
325   //! @return true if reversion success.
326   bool Inverted (NCollection_Mat4<Element_t>& theOutMx) const
327   {
328     Element_t* inv = theOutMx.myMat;
329
330     // use short-cut for better readability
331     const Element_t* m = myMat;
332
333     inv[ 0] = m[ 5] * (m[10] * m[15] - m[11] * m[14]) -
334               m[ 9] * (m[ 6] * m[15] - m[ 7] * m[14]) -
335               m[13] * (m[ 7] * m[10] - m[ 6] * m[11]);
336
337     inv[ 1] = m[ 1] * (m[11] * m[14] - m[10] * m[15]) -
338               m[ 9] * (m[ 3] * m[14] - m[ 2] * m[15]) -
339               m[13] * (m[ 2] * m[11] - m[ 3] * m[10]);
340
341     inv[ 2] = m[ 1] * (m[ 6] * m[15] - m[ 7] * m[14]) -
342               m[ 5] * (m[ 2] * m[15] - m[ 3] * m[14]) -
343               m[13] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
344
345     inv[ 3] = m[ 1] * (m[ 7] * m[10] - m[ 6] * m[11]) -
346               m[ 5] * (m[ 3] * m[10] - m[ 2] * m[11]) -
347               m[ 9] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
348
349     inv[ 4] = m[ 4] * (m[11] * m[14] - m[10] * m[15]) -
350               m[ 8] * (m[ 7] * m[14] - m[ 6] * m[15]) -
351               m[12] * (m[ 6] * m[11] - m[ 7] * m[10]);
352
353     inv[ 5] = m[ 0] * (m[10] * m[15] - m[11] * m[14]) -
354               m[ 8] * (m[ 2] * m[15] - m[ 3] * m[14]) -
355               m[12] * (m[ 3] * m[10] - m[ 2] * m[11]);
356
357     inv[ 6] = m[ 0] * (m[ 7] * m[14] - m[ 6] * m[15]) -
358               m[ 4] * (m[ 3] * m[14] - m[ 2] * m[15]) -
359               m[12] * (m[ 2] * m[ 7] - m[ 3] * m[ 6]);
360
361     inv[ 7] = m[ 0] * (m[ 6] * m[11] - m[ 7] * m[10]) -
362               m[ 4] * (m[ 2] * m[11] - m[ 3] * m[10]) -
363               m[ 8] * (m[ 3] * m[ 6] - m[ 2] * m[ 7]);
364
365     inv[ 8] = m[ 4] * (m[ 9] * m[15] - m[11] * m[13]) -
366               m[ 8] * (m[ 5] * m[15] - m[ 7] * m[13]) -
367               m[12] * (m[ 7] * m[ 9] - m[ 5] * m[11]);
368
369     inv[ 9] = m[ 0] * (m[11] * m[13] - m[ 9] * m[15]) -
370               m[ 8] * (m[ 3] * m[13] - m[ 1] * m[15]) -
371               m[12] * (m[ 1] * m[11] - m[ 3] * m[ 9]);
372
373     inv[10] = m[ 0] * (m[ 5] * m[15] - m[ 7] * m[13]) -
374               m[ 4] * (m[ 1] * m[15] - m[ 3] * m[13]) -
375               m[12] * (m[ 3] * m[ 5] - m[ 1] * m[ 7]);
376
377     inv[11] = m[ 0] * (m[ 7] * m[ 9] - m[ 5] * m[11]) -
378               m[ 4] * (m[ 3] * m[ 9] - m[ 1] * m[11]) -
379               m[ 8] * (m[ 1] * m[ 7] - m[ 3] * m[ 5]);
380
381     inv[12] = m[ 4] * (m[10] * m[13] - m[ 9] * m[14]) -
382               m[ 8] * (m[ 6] * m[13] - m[ 5] * m[14]) -
383               m[12] * (m[ 5] * m[10] - m[ 6] * m[ 9]);
384
385     inv[13] = m[ 0] * (m[ 9] * m[14] - m[10] * m[13]) -
386               m[ 8] * (m[ 1] * m[14] - m[ 2] * m[13]) -
387               m[12] * (m[ 2] * m[ 9] - m[ 1] * m[10]);
388
389     inv[14] = m[ 0] * (m[ 6] * m[13] - m[ 5] * m[14]) -
390               m[ 4] * (m[ 2] * m[13] - m[ 1] * m[14]) -
391               m[12] * (m[ 1] * m[ 6] - m[ 2] * m[ 5]);
392
393     inv[15] = m[ 0] * (m[ 5] * m[10] - m[ 6] * m[ 9]) -
394               m[ 4] * (m[ 1] * m[10] - m[ 2] * m[ 9]) -
395               m[ 8] * (m[ 2] * m[ 5] - m[ 1] * m[ 6]);
396
397     Element_t aDet = m[0] * inv[ 0] +
398                      m[1] * inv[ 4] +
399                      m[2] * inv[ 8] +
400                      m[3] * inv[12];
401
402     if (aDet == 0)
403       return false;
404
405     aDet = (Element_t) 1. / aDet;
406
407     for (int i = 0; i < 16; ++i)
408       inv[i] *= aDet;
409
410     return true;
411   }
412
413   // Converts NCollection_Mat4 with different element type.
414   template <typename Other_t>
415   void Convert (const NCollection_Mat4<Other_t>& theOther)
416   {
417     for (int anIdx = 0; anIdx < 16; ++anIdx)
418     {
419       myMat[anIdx] = static_cast<Element_t> (theOther.myMat[anIdx]);
420     }
421   }
422
423   //! Maps plain C array to matrix type.
424   static NCollection_Mat4<Element_t>& Map (Element_t* theData)
425   {
426     return *reinterpret_cast<NCollection_Mat4<Element_t>*> (theData);
427   }
428
429   //! Maps plain C array to matrix type.
430   static const NCollection_Mat4<Element_t>& Map (const Element_t* theData)
431   {
432     return *reinterpret_cast<const NCollection_Mat4<Element_t>*> (theData);
433   }
434
435 private:
436
437   Element_t myMat[16];
438
439 private:
440
441   static Element_t myIdentityArray[16];
442
443   // All instantiations are friend to each other
444   template<class OtherType> friend class NCollection_Mat4;
445
446 };
447
448 template<typename Element_t>
449 Element_t NCollection_Mat4<Element_t>::myIdentityArray[] =
450   {1, 0, 0, 0,
451    0, 1, 0, 0,
452    0, 0, 1, 0,
453    0, 0, 0, 1};
454
455 #endif // _NCollection_Mat4_HeaderFile