30f0ad28 |
1 | // Created on: 2013-05-30 |
2 | // Created by: Anton POLETAEV |
d5f74e42 |
3 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
30f0ad28 |
4 | // |
973c2be1 |
5 | // This file is part of Open CASCADE Technology software library. |
30f0ad28 |
6 | // |
d5f74e42 |
7 | // This library is free software; you can redistribute it and/or modify it under |
8 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
9 | // by the Free Software Foundation, with special exception defined in the file |
10 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
11 | // distribution for complete text of the license and disclaimer of any warranty. |
30f0ad28 |
12 | // |
973c2be1 |
13 | // Alternatively, this file may be used under the terms of Open CASCADE |
14 | // commercial license or contractual agreement. |
30f0ad28 |
15 | |
16 | #ifndef _NCollection_Mat4_HeaderFile |
17 | #define _NCollection_Mat4_HeaderFile |
18 | |
19 | #include <NCollection_Vec4.hxx> |
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 | |
30f0ad28 |
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 | { |
197ac94e |
179 | std::memcpy (this, myIdentityArray, sizeof (NCollection_Mat4)); |
180 | } |
30f0ad28 |
181 | |
197ac94e |
182 | //! Checks the matrix for identity. |
183 | bool IsIdentity() const |
184 | { |
185 | return std::memcmp (this, myIdentityArray, sizeof (NCollection_Mat4)) == 0; |
30f0ad28 |
186 | } |
187 | |
188 | //! Raw access to the data (for OpenGL exchange). |
938d4544 |
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; } |
30f0ad28 |
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 | { |
938d4544 |
247 | return Multiplied (theMat); |
30f0ad28 |
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 | |
938d4544 |
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 | |
30f0ad28 |
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 | |
778cd667 |
413 | //! Take values from NCollection_Mat4 with a different element type with type conversion. |
c827ea3a |
414 | template <typename Other_t> |
778cd667 |
415 | void ConvertFrom (const NCollection_Mat4<Other_t>& theFrom) |
c827ea3a |
416 | { |
417 | for (int anIdx = 0; anIdx < 16; ++anIdx) |
418 | { |
778cd667 |
419 | myMat[anIdx] = static_cast<Element_t> (theFrom.myMat[anIdx]); |
c827ea3a |
420 | } |
421 | } |
422 | |
778cd667 |
423 | //! Take values from NCollection_Mat4 with a different element type with type conversion. |
424 | template <typename Other_t> |
425 | void Convert (const NCollection_Mat4<Other_t>& theFrom) { ConvertFrom (theFrom); } |
426 | |
c827ea3a |
427 | //! Maps plain C array to matrix type. |
428 | static NCollection_Mat4<Element_t>& Map (Element_t* theData) |
429 | { |
430 | return *reinterpret_cast<NCollection_Mat4<Element_t>*> (theData); |
431 | } |
432 | |
433 | //! Maps plain C array to matrix type. |
434 | static const NCollection_Mat4<Element_t>& Map (const Element_t* theData) |
435 | { |
436 | return *reinterpret_cast<const NCollection_Mat4<Element_t>*> (theData); |
437 | } |
438 | |
30f0ad28 |
439 | private: |
440 | |
441 | Element_t myMat[16]; |
442 | |
197ac94e |
443 | private: |
444 | |
445 | static Element_t myIdentityArray[16]; |
c827ea3a |
446 | |
447 | // All instantiations are friend to each other |
448 | template<class OtherType> friend class NCollection_Mat4; |
449 | |
30f0ad28 |
450 | }; |
451 | |
197ac94e |
452 | template<typename Element_t> |
453 | Element_t NCollection_Mat4<Element_t>::myIdentityArray[] = |
454 | {1, 0, 0, 0, |
455 | 0, 1, 0, 0, |
456 | 0, 0, 1, 0, |
457 | 0, 0, 0, 1}; |
458 | |
938d4544 |
459 | #endif // _NCollection_Mat4_HeaderFile |