1 | // Copyright (C) 2015-2015 ChaosForge Ltd
|
---|
2 | // http://chaosforge.org/
|
---|
3 | //
|
---|
4 | // This file is part of Nova libraries.
|
---|
5 | // For conditions of distribution and use, see copying.txt file in root folder.
|
---|
6 |
|
---|
7 | /**
|
---|
8 | * @file mat4.hh
|
---|
9 | * @author Kornel Kisielewicz epyon@chaosforge.org
|
---|
10 | * @brief matrix 4x4
|
---|
11 | */
|
---|
12 |
|
---|
13 | #ifndef NV_STL_MATH_MAT4_HH
|
---|
14 | #define NV_STL_MATH_MAT4_HH
|
---|
15 |
|
---|
16 | #include <nv/stl/math/common.hh>
|
---|
17 |
|
---|
18 | namespace nv
|
---|
19 | {
|
---|
20 |
|
---|
21 | namespace math
|
---|
22 | {
|
---|
23 |
|
---|
24 | template <typename T>
|
---|
25 | struct tmat4
|
---|
26 | {
|
---|
27 | typedef tvec4<T> column_type;
|
---|
28 | typedef tvec4<T> row_type;
|
---|
29 | typedef tmat4<T> this_type;
|
---|
30 | typedef size_t size_type;
|
---|
31 | typedef T value_type;
|
---|
32 |
|
---|
33 | static constexpr size_type SIZE = 4;
|
---|
34 | inline constexpr size_type size() const { return 4; }
|
---|
35 |
|
---|
36 | private:
|
---|
37 | column_type value[4];
|
---|
38 |
|
---|
39 | public:
|
---|
40 | inline tmat4()
|
---|
41 | : value{
|
---|
42 | column_type( static_cast<T>( 1 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ),
|
---|
43 | column_type( static_cast<T>( 0 ), static_cast<T>( 1 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ),
|
---|
44 | column_type( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 1 ), static_cast<T>( 0 ) ),
|
---|
45 | column_type( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 1 ) )
|
---|
46 | }
|
---|
47 | {}
|
---|
48 |
|
---|
49 | inline tmat4( const tmat4<T> & m ) = default;
|
---|
50 | inline tmat4( tmat4<T> && m ) = default;
|
---|
51 | inline tmat4<T> & operator=( const tmat4<T> & m ) = default;
|
---|
52 | inline tmat4<T> & operator=( tmat4<T> && m ) = default;
|
---|
53 |
|
---|
54 | inline explicit tmat4( T s )
|
---|
55 | : value{
|
---|
56 | column_type( static_cast<T>( s ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ) ),
|
---|
57 | column_type( static_cast<T>( 0 ), static_cast<T>( s ), static_cast<T>( 0 ), static_cast<T>( 0 ) ),
|
---|
58 | column_type( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( s ), static_cast<T>( 0 ) ),
|
---|
59 | column_type( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( s ) )
|
---|
60 | }
|
---|
61 | {}
|
---|
62 |
|
---|
63 | inline explicit tmat4( no_init_t )
|
---|
64 | : value{
|
---|
65 | column_type( no_init ),
|
---|
66 | column_type( no_init ),
|
---|
67 | column_type( no_init ),
|
---|
68 | column_type( no_init )
|
---|
69 | }
|
---|
70 | {}
|
---|
71 |
|
---|
72 | inline tmat4(
|
---|
73 | T x0, T y0, T z0, T w0,
|
---|
74 | T x1, T y1, T z1, T w1,
|
---|
75 | T x2, T y2, T z2, T w2,
|
---|
76 | T x3, T y3, T z3, T w3
|
---|
77 | ) : value{
|
---|
78 | column_type( x0, y0, z0, w0 ),
|
---|
79 | column_type( x1, y1, z1, w1 ),
|
---|
80 | column_type( x2, y2, z2, w2 ),
|
---|
81 | column_type( x3, y3, z3, w3 )
|
---|
82 | }
|
---|
83 | {}
|
---|
84 |
|
---|
85 | inline tmat4(
|
---|
86 | const column_type & v0,
|
---|
87 | const column_type & v1,
|
---|
88 | const column_type & v2,
|
---|
89 | const column_type & v3
|
---|
90 | ) : value{ v0, v1, v2, v3 }
|
---|
91 | {}
|
---|
92 |
|
---|
93 | template <typename U>
|
---|
94 | inline explicit tmat4( const tmat4<U> & m )
|
---|
95 | : value{
|
---|
96 | column_type( m[0] ),
|
---|
97 | column_type( m[1] ),
|
---|
98 | column_type( m[2] ),
|
---|
99 | column_type( m[3] )
|
---|
100 | }
|
---|
101 | {}
|
---|
102 |
|
---|
103 | inline explicit tmat4( const tmat2<T> & m )
|
---|
104 | : value{
|
---|
105 | column_type( m[0], static_cast<T>( 0 ), static_cast<T>( 0 ) ),
|
---|
106 | column_type( m[1], static_cast<T>( 0 ), static_cast<T>( 0 ) ),
|
---|
107 | column_type( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 1 ), static_cast<T>( 0 ) ),
|
---|
108 | column_type( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 1 ) )
|
---|
109 | }
|
---|
110 | {}
|
---|
111 |
|
---|
112 | inline explicit tmat4( const tmat3<T> & m )
|
---|
113 | : value{
|
---|
114 | column_type( m[0], static_cast<T>( 0 ) ),
|
---|
115 | column_type( m[1], static_cast<T>( 0 ) ),
|
---|
116 | column_type( m[2], static_cast<T>( 0 ) ),
|
---|
117 | column_type( static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 0 ), static_cast<T>( 1 ) )
|
---|
118 | }
|
---|
119 | {}
|
---|
120 |
|
---|
121 | inline column_type & operator[]( size_type i )
|
---|
122 | {
|
---|
123 | NV_ASSERT_DEBUG( i >= 0 && i < this->size(), "index out of range!" );
|
---|
124 | return this->value[i];
|
---|
125 | }
|
---|
126 |
|
---|
127 | inline const column_type& operator[]( size_type i ) const
|
---|
128 | {
|
---|
129 | NV_ASSERT_DEBUG( i >= 0 && i < this->size(), "index out of range!" );
|
---|
130 | return this->value[i];
|
---|
131 | }
|
---|
132 |
|
---|
133 | inline tmat4<T>& operator+=( T s )
|
---|
134 | {
|
---|
135 | this->value[0] += s;
|
---|
136 | this->value[1] += s;
|
---|
137 | this->value[2] += s;
|
---|
138 | this->value[3] += s;
|
---|
139 | return *this;
|
---|
140 | }
|
---|
141 |
|
---|
142 | inline tmat4<T>& operator+=( const tmat4<T> & m )
|
---|
143 | {
|
---|
144 | this->value[0] += m[0];
|
---|
145 | this->value[1] += m[1];
|
---|
146 | this->value[2] += m[2];
|
---|
147 | this->value[3] += m[3];
|
---|
148 | return *this;
|
---|
149 | }
|
---|
150 |
|
---|
151 | inline tmat4<T> & operator-=( T s )
|
---|
152 | {
|
---|
153 | this->value[0] -= s;
|
---|
154 | this->value[1] -= s;
|
---|
155 | this->value[2] -= s;
|
---|
156 | this->value[3] -= s;
|
---|
157 | return *this;
|
---|
158 | }
|
---|
159 |
|
---|
160 | inline tmat4<T> & operator-=( const tmat4<T> & m )
|
---|
161 | {
|
---|
162 | this->value[0] -= m[0];
|
---|
163 | this->value[1] -= m[1];
|
---|
164 | this->value[2] -= m[2];
|
---|
165 | this->value[3] -= m[3];
|
---|
166 | return *this;
|
---|
167 | }
|
---|
168 |
|
---|
169 | inline tmat4<T> & operator*=( T s )
|
---|
170 | {
|
---|
171 | this->value[0] *= s;
|
---|
172 | this->value[1] *= s;
|
---|
173 | this->value[2] *= s;
|
---|
174 | this->value[3] *= s;
|
---|
175 | return *this;
|
---|
176 | }
|
---|
177 |
|
---|
178 | inline tmat4<T> & operator*=( const tmat4<T> & m )
|
---|
179 | {
|
---|
180 | return ( *this = *this * m );
|
---|
181 | }
|
---|
182 |
|
---|
183 | inline tmat4<T> & operator/=( T s )
|
---|
184 | {
|
---|
185 | this->value[0] /= s;
|
---|
186 | this->value[1] /= s;
|
---|
187 | this->value[2] /= s;
|
---|
188 | this->value[3] /= s;
|
---|
189 | return *this;
|
---|
190 | }
|
---|
191 |
|
---|
192 | inline tmat4<T> & operator/=( const tmat4<T> & m )
|
---|
193 | {
|
---|
194 | return ( *this = *this * detail::compute_inverse<T>( m ) );
|
---|
195 | }
|
---|
196 |
|
---|
197 | inline tmat4<T> & operator++()
|
---|
198 | {
|
---|
199 | ++this->value[0];
|
---|
200 | ++this->value[1];
|
---|
201 | ++this->value[2];
|
---|
202 | ++this->value[3];
|
---|
203 | return *this;
|
---|
204 | }
|
---|
205 |
|
---|
206 | inline tmat4<T> & operator--()
|
---|
207 | {
|
---|
208 | --this->value[0];
|
---|
209 | --this->value[1];
|
---|
210 | --this->value[2];
|
---|
211 | --this->value[3];
|
---|
212 | return *this;
|
---|
213 | }
|
---|
214 |
|
---|
215 | inline tmat4<T> operator++( int )
|
---|
216 | {
|
---|
217 | tmat4<T> result( *this );
|
---|
218 | ++*this;
|
---|
219 | return result;
|
---|
220 | }
|
---|
221 |
|
---|
222 | inline tmat4<T> operator--( int )
|
---|
223 | {
|
---|
224 | tmat4<T> result( *this );
|
---|
225 | --*this;
|
---|
226 | return result;
|
---|
227 | }
|
---|
228 |
|
---|
229 | };
|
---|
230 |
|
---|
231 | namespace detail
|
---|
232 | {
|
---|
233 | template <typename T>
|
---|
234 | inline tmat4<T> compute_inverse( const tmat4<T> & m )
|
---|
235 | {
|
---|
236 | T cf00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
---|
237 | T cf02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
|
---|
238 | T cf03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
|
---|
239 |
|
---|
240 | T cf04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
|
---|
241 | T cf06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
---|
242 | T cf07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
|
---|
243 |
|
---|
244 | T cf08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
|
---|
245 | T cf10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
|
---|
246 | T cf11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
|
---|
247 |
|
---|
248 | T cf12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
|
---|
249 | T cf14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
|
---|
250 | T cf15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
|
---|
251 |
|
---|
252 | T cf16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
|
---|
253 | T cf18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
|
---|
254 | T cf19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
|
---|
255 |
|
---|
256 | T cf20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
|
---|
257 | T cf22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
|
---|
258 | T cf23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
|
---|
259 |
|
---|
260 | tvec4<T> f0( cf00, cf00, cf02, cf03 );
|
---|
261 | tvec4<T> f1( cf04, cf04, cf06, cf07 );
|
---|
262 | tvec4<T> f2( cf08, cf08, cf10, cf11 );
|
---|
263 | tvec4<T> f3( cf12, cf12, cf14, cf15 );
|
---|
264 | tvec4<T> f4( cf16, cf16, cf18, cf19 );
|
---|
265 | tvec4<T> f5( cf20, cf20, cf22, cf23 );
|
---|
266 |
|
---|
267 | tvec4<T> v0( m[1][0], m[0][0], m[0][0], m[0][0] );
|
---|
268 | tvec4<T> v1( m[1][1], m[0][1], m[0][1], m[0][1] );
|
---|
269 | tvec4<T> v2( m[1][2], m[0][2], m[0][2], m[0][2] );
|
---|
270 | tvec4<T> v3( m[1][3], m[0][3], m[0][3], m[0][3] );
|
---|
271 |
|
---|
272 | tvec4<T> i0( v1 * f0 - v2 * f1 + v3 * f2 );
|
---|
273 | tvec4<T> i1( v0 * f0 - v2 * f3 + v3 * f4 );
|
---|
274 | tvec4<T> i2( v0 * f1 - v1 * f3 + v3 * f5 );
|
---|
275 | tvec4<T> i3( v0 * f2 - v1 * f4 + v2 * f5 );
|
---|
276 |
|
---|
277 | tvec4<T> sgn_a( +1, -1, +1, -1 );
|
---|
278 | tvec4<T> sgn_b( -1, +1, -1, +1 );
|
---|
279 | tmat4<T> inv( i0 * sgn_a, i1 * sgn_b, i2 * sgn_a, i3 * sgn_b );
|
---|
280 |
|
---|
281 | tvec4<T> rz( inv[0][0], inv[1][0], inv[2][0], inv[3][0] );
|
---|
282 | tvec4<T> d0( m[0] * rz );
|
---|
283 | T d1 = ( d0.x + d0.y ) + ( d0.z + d0.w );
|
---|
284 | T one_over_det = static_cast<T>( 1 ) / d1;
|
---|
285 |
|
---|
286 | return inv * one_over_det;
|
---|
287 | }
|
---|
288 |
|
---|
289 | }
|
---|
290 |
|
---|
291 |
|
---|
292 | template <typename T>
|
---|
293 | inline tmat4<T> const operator-( const tmat4<T> & m )
|
---|
294 | {
|
---|
295 | return tmat4<T>(
|
---|
296 | -m[0],
|
---|
297 | -m[1],
|
---|
298 | -m[2],
|
---|
299 | -m[3] );
|
---|
300 | }
|
---|
301 |
|
---|
302 | template <typename T>
|
---|
303 | inline tmat4<T> operator+( const tmat4<T> & m, T s )
|
---|
304 | {
|
---|
305 | return tmat4<T>(
|
---|
306 | m[0] + s,
|
---|
307 | m[1] + s,
|
---|
308 | m[2] + s,
|
---|
309 | m[3] + s );
|
---|
310 | }
|
---|
311 |
|
---|
312 | template <typename T>
|
---|
313 | inline tmat4<T> operator+( T s, const tmat4<T> & m )
|
---|
314 | {
|
---|
315 | return tmat4<T>(
|
---|
316 | m[0] + s,
|
---|
317 | m[1] + s,
|
---|
318 | m[2] + s,
|
---|
319 | m[3] + s );
|
---|
320 | }
|
---|
321 |
|
---|
322 | template <typename T>
|
---|
323 | inline tmat4<T> operator+( const tmat4<T> & m1, const tmat4<T> & m2 )
|
---|
324 | {
|
---|
325 | return tmat4<T>(
|
---|
326 | m1[0] + m2[0],
|
---|
327 | m1[1] + m2[1],
|
---|
328 | m1[2] + m2[2],
|
---|
329 | m1[3] + m2[3] );
|
---|
330 | }
|
---|
331 |
|
---|
332 | template <typename T>
|
---|
333 | inline tmat4<T> operator-( const tmat4<T> & m, T s )
|
---|
334 | {
|
---|
335 | return tmat4<T>(
|
---|
336 | m[0] - s,
|
---|
337 | m[1] - s,
|
---|
338 | m[2] - s,
|
---|
339 | m[3] - s );
|
---|
340 | }
|
---|
341 |
|
---|
342 | template <typename T>
|
---|
343 | inline tmat4<T> operator-( T s, const tmat4<T> & m )
|
---|
344 | {
|
---|
345 | return tmat4<T>(
|
---|
346 | s - m[0],
|
---|
347 | s - m[1],
|
---|
348 | s - m[2],
|
---|
349 | s - m[3] );
|
---|
350 | }
|
---|
351 |
|
---|
352 | template <typename T>
|
---|
353 | inline tmat4<T> operator-( const tmat4<T> & m1, const tmat4<T> & m2 )
|
---|
354 | {
|
---|
355 | return tmat4<T>(
|
---|
356 | m1[0] - m2[0],
|
---|
357 | m1[1] - m2[1],
|
---|
358 | m1[2] - m2[2],
|
---|
359 | m1[3] - m2[3] );
|
---|
360 | }
|
---|
361 |
|
---|
362 | template <typename T>
|
---|
363 | inline tmat4<T> operator*( const tmat4<T> & m, T s )
|
---|
364 | {
|
---|
365 | return tmat4<T>(
|
---|
366 | m[0] * s,
|
---|
367 | m[1] * s,
|
---|
368 | m[2] * s,
|
---|
369 | m[3] * s );
|
---|
370 | }
|
---|
371 |
|
---|
372 | template <typename T>
|
---|
373 | inline tmat4<T> operator*( T s, const tmat4<T> & m )
|
---|
374 | {
|
---|
375 | return tmat4<T>(
|
---|
376 | m[0] * s,
|
---|
377 | m[1] * s,
|
---|
378 | m[2] * s,
|
---|
379 | m[3] * s );
|
---|
380 | }
|
---|
381 |
|
---|
382 | template <typename T>
|
---|
383 | inline typename tmat4<T>::column_type operator*( const tmat4<T> & m, const typename tmat4<T>::row_type & v )
|
---|
384 | {
|
---|
385 | typedef typename tmat4<T>::column_type column_type;
|
---|
386 | column_type u0 = m[0] * column_type( v[0] );
|
---|
387 | column_type u1 = m[1] * column_type( v[1] );
|
---|
388 | column_type u2 = m[2] * column_type( v[2] );
|
---|
389 | column_type u3 = m[3] * column_type( v[3] );
|
---|
390 | return ( u0 + u1 ) + ( u2 + u3 );
|
---|
391 | }
|
---|
392 |
|
---|
393 | template <typename T>
|
---|
394 | inline typename tmat4<T>::row_type operator* ( const typename tmat4<T>::column_type & v, const tmat4<T> & m )
|
---|
395 | {
|
---|
396 | return typename tmat4<T>::row_type(
|
---|
397 | m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3],
|
---|
398 | m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3],
|
---|
399 | m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3],
|
---|
400 | m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]
|
---|
401 | );
|
---|
402 | }
|
---|
403 |
|
---|
404 | template <typename T>
|
---|
405 | inline tmat4<T> operator*( const tmat4<T> & m1, const tmat4<T> & m2 )
|
---|
406 | {
|
---|
407 | typedef typename tmat4<T>::column_type column_type;
|
---|
408 | column_type m2_0 = m2[0];
|
---|
409 | column_type m2_1 = m2[1];
|
---|
410 | column_type m2_2 = m2[2];
|
---|
411 | column_type m2_3 = m2[3];
|
---|
412 |
|
---|
413 | tmat4<T> result( no_init );
|
---|
414 | result[0] = m1[0] * m2_0[0] + m1[1] * m2_0[1] + m1[2] * m2_0[2] + m1[3] * m2_0[3];
|
---|
415 | result[1] = m1[0] * m2_1[0] + m1[1] * m2_1[1] + m1[2] * m2_1[2] + m1[3] * m2_1[3];
|
---|
416 | result[2] = m1[0] * m2_2[0] + m1[1] * m2_2[1] + m1[2] * m2_2[2] + m1[3] * m2_2[3];
|
---|
417 | result[3] = m1[0] * m2_3[0] + m1[1] * m2_3[1] + m1[2] * m2_3[2] + m1[3] * m2_3[3];
|
---|
418 | return result;
|
---|
419 | }
|
---|
420 |
|
---|
421 | template <typename T>
|
---|
422 | inline tmat4<T> operator/( const tmat4<T> & m, T s )
|
---|
423 | {
|
---|
424 | return tmat4<T>(
|
---|
425 | m[0] / s,
|
---|
426 | m[1] / s,
|
---|
427 | m[2] / s,
|
---|
428 | m[3] / s );
|
---|
429 | }
|
---|
430 |
|
---|
431 | template <typename T>
|
---|
432 | inline tmat4<T> operator/( T s, const tmat4<T> & m )
|
---|
433 | {
|
---|
434 | return tmat4<T>(
|
---|
435 | s / m[0],
|
---|
436 | s / m[1],
|
---|
437 | s / m[2],
|
---|
438 | s / m[3] );
|
---|
439 | }
|
---|
440 |
|
---|
441 | template <typename T>
|
---|
442 | inline typename tmat4<T>::column_type operator/( const tmat4<T> & m, typename tmat4<T>::row_type const & v )
|
---|
443 | {
|
---|
444 | return detail::compute_inverse<T>( m ) * v;
|
---|
445 | }
|
---|
446 |
|
---|
447 | template <typename T>
|
---|
448 | inline typename tmat4<T>::row_type operator/( typename tmat4<T>::column_type const & v, const tmat4<T> & m )
|
---|
449 | {
|
---|
450 | return v * detail::compute_inverse<T>( m );
|
---|
451 | }
|
---|
452 |
|
---|
453 | template <typename T>
|
---|
454 | inline tmat4<T> operator/( const tmat4<T> & m1, const tmat4<T> & m2 )
|
---|
455 | {
|
---|
456 | tmat4<T> m1_copy( m1 );
|
---|
457 | return m1_copy /= m2;
|
---|
458 | }
|
---|
459 |
|
---|
460 | template <typename T>
|
---|
461 | inline bool operator==( const tmat4<T> & m1, const tmat4<T> & m2 )
|
---|
462 | {
|
---|
463 | return ( m1[0] == m2[0] ) && ( m1[1] == m2[1] ) && ( m1[2] == m2[2] ) && ( m1[3] == m2[3] );
|
---|
464 | }
|
---|
465 |
|
---|
466 | template <typename T>
|
---|
467 | inline bool operator!=( const tmat4<T> & m1, const tmat4<T> & m2 )
|
---|
468 | {
|
---|
469 | return ( m1[0] != m2[0] ) || ( m1[1] != m2[1] ) || ( m1[2] != m2[2] ) || ( m1[3] != m2[3] );
|
---|
470 | }
|
---|
471 | }
|
---|
472 |
|
---|
473 | }
|
---|
474 |
|
---|
475 | #endif // NV_STL_MATH_MAT4_HH
|
---|