blob: 61bbfbf40bfb1bc412713883b7413cda0037be70 [file] [log] [blame]
Tony-LunarGb0b195d2015-05-13 15:01:06 -06001///////////////////////////////////////////////////////////////////////////////////
2/// OpenGL Mathematics (glm.g-truc.net)
3///
4/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
5/// Permission is hereby granted, free of charge, to any person obtaining a copy
6/// of this software and associated documentation files (the "Software"), to deal
7/// in the Software without restriction, including without limitation the rights
8/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9/// copies of the Software, and to permit persons to whom the Software is
10/// furnished to do so, subject to the following conditions:
11///
12/// The above copyright notice and this permission notice shall be included in
13/// all copies or substantial portions of the Software.
14///
15/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21/// THE SOFTWARE.
22///
23/// @ref core
24/// @file glm/core/func_matrix.inl
25/// @date 2008-03-08 / 2011-06-15
26/// @author Christophe Riccio
27///////////////////////////////////////////////////////////////////////////////////
28
29#include "../geometric.hpp"
30#include <limits>
31
32namespace glm{
33namespace detail
34{
35 template
36 <
37 template <class, precision> class vecTypeA,
38 template <class, precision> class vecTypeB,
39 typename T, precision P
40 >
41 struct compute_outerProduct{};
42
43 template <typename T, precision P>
44 struct compute_outerProduct<detail::tvec2, detail::tvec2, T, P>
45 {
46 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec2, detail::tvec2>::type call(detail::tvec2<T, P> const & c, detail::tvec2<T, P> const & r)
47 {
48 detail::tmat2x2<T, P> m(detail::tmat2x2<T, P>::_null);
49 m[0][0] = c[0] * r[0];
50 m[0][1] = c[1] * r[0];
51 m[1][0] = c[0] * r[1];
52 m[1][1] = c[1] * r[1];
53 return m;
54 }
55 };
56
57 template <typename T, precision P>
58 struct compute_outerProduct<detail::tvec3, detail::tvec3, T, P>
59 {
60 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec3, detail::tvec3>::type call(detail::tvec3<T, P> const & c, detail::tvec3<T, P> const & r)
61 {
62 detail::tmat3x3<T, P> m(detail::tmat3x3<T, P>::_null);
63 for(length_t i(0); i < m.length(); ++i)
64 m[i] = c * r[i];
65 return m;
66 }
67 };
68
69 template <typename T, precision P>
70 struct compute_outerProduct<detail::tvec4, detail::tvec4, T, P>
71 {
72 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec4, detail::tvec4>::type call(detail::tvec4<T, P> const & c, detail::tvec4<T, P> const & r)
73 {
74 detail::tmat4x4<T, P> m(detail::tmat4x4<T, P>::_null);
75 for(length_t i(0); i < m.length(); ++i)
76 m[i] = c * r[i];
77 return m;
78 }
79 };
80
81 template <typename T, precision P>
82 struct compute_outerProduct<detail::tvec3, detail::tvec2, T, P>
83 {
84 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec3, detail::tvec2>::type call(detail::tvec3<T, P> const & c, detail::tvec2<T, P> const & r)
85 {
86 detail::tmat2x3<T, P> m(detail::tmat2x3<T, P>::_null);
87 m[0][0] = c.x * r.x;
88 m[0][1] = c.y * r.x;
89 m[0][2] = c.z * r.x;
90 m[1][0] = c.x * r.y;
91 m[1][1] = c.y * r.y;
92 m[1][2] = c.z * r.y;
93 return m;
94 }
95 };
96
97 template <typename T, precision P>
98 struct compute_outerProduct<detail::tvec2, detail::tvec3, T, P>
99 {
100 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec2, detail::tvec3>::type call(detail::tvec2<T, P> const & c, detail::tvec3<T, P> const & r)
101 {
102 detail::tmat3x2<T, P> m(detail::tmat3x2<T, P>::_null);
103 m[0][0] = c.x * r.x;
104 m[0][1] = c.y * r.x;
105 m[1][0] = c.x * r.y;
106 m[1][1] = c.y * r.y;
107 m[2][0] = c.x * r.z;
108 m[2][1] = c.y * r.z;
109 return m;
110 }
111 };
112
113 template <typename T, precision P>
114 struct compute_outerProduct<detail::tvec4, detail::tvec2, T, P>
115 {
116 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec4, detail::tvec2>::type call(detail::tvec4<T, P> const & c, detail::tvec2<T, P> const & r)
117 {
118 detail::tmat2x4<T, P> m(detail::tmat2x4<T, P>::_null);
119 m[0][0] = c.x * r.x;
120 m[0][1] = c.y * r.x;
121 m[0][2] = c.z * r.x;
122 m[0][3] = c.w * r.x;
123 m[1][0] = c.x * r.y;
124 m[1][1] = c.y * r.y;
125 m[1][2] = c.z * r.y;
126 m[1][3] = c.w * r.y;
127 return m;
128 }
129 };
130
131 template <typename T, precision P>
132 struct compute_outerProduct<detail::tvec2, detail::tvec4, T, P>
133 {
134 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec2, detail::tvec4>::type call(detail::tvec2<T, P> const & c, detail::tvec4<T, P> const & r)
135 {
136 detail::tmat4x2<T, P> m(detail::tmat4x2<T, P>::_null);
137 m[0][0] = c.x * r.x;
138 m[0][1] = c.y * r.x;
139 m[1][0] = c.x * r.y;
140 m[1][1] = c.y * r.y;
141 m[2][0] = c.x * r.z;
142 m[2][1] = c.y * r.z;
143 m[3][0] = c.x * r.w;
144 m[3][1] = c.y * r.w;
145 return m;
146 }
147 };
148
149 template <typename T, precision P>
150 struct compute_outerProduct<detail::tvec4, detail::tvec3, T, P>
151 {
152 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec4, detail::tvec3>::type call(detail::tvec4<T, P> const & c, detail::tvec3<T, P> const & r)
153 {
154 detail::tmat3x4<T, P> m(detail::tmat3x4<T, P>::_null);
155 m[0][0] = c.x * r.x;
156 m[0][1] = c.y * r.x;
157 m[0][2] = c.z * r.x;
158 m[0][3] = c.w * r.x;
159 m[1][0] = c.x * r.y;
160 m[1][1] = c.y * r.y;
161 m[1][2] = c.z * r.y;
162 m[1][3] = c.w * r.y;
163 m[2][0] = c.x * r.z;
164 m[2][1] = c.y * r.z;
165 m[2][2] = c.z * r.z;
166 m[2][3] = c.w * r.z;
167 return m;
168 }
169 };
170
171 template <typename T, precision P>
172 struct compute_outerProduct<detail::tvec3, detail::tvec4, T, P>
173 {
174 GLM_FUNC_QUALIFIER static typename detail::outerProduct_trait<T, P, detail::tvec3, detail::tvec4>::type call(detail::tvec3<T, P> const & c, detail::tvec4<T, P> const & r)
175 {
176 detail::tmat4x3<T, P> m(detail::tmat4x3<T, P>::_null);
177 m[0][0] = c.x * r.x;
178 m[0][1] = c.y * r.x;
179 m[0][2] = c.z * r.x;
180 m[1][0] = c.x * r.y;
181 m[1][1] = c.y * r.y;
182 m[1][2] = c.z * r.y;
183 m[2][0] = c.x * r.z;
184 m[2][1] = c.y * r.z;
185 m[2][2] = c.z * r.z;
186 m[3][0] = c.x * r.w;
187 m[3][1] = c.y * r.w;
188 m[3][2] = c.z * r.w;
189 return m;
190 }
191 };
192
193 template <template <class, precision> class matType, typename T, precision P>
194 struct compute_transpose{};
195
196 template <typename T, precision P>
197 struct compute_transpose<detail::tmat2x2, T, P>
198 {
199 GLM_FUNC_QUALIFIER static detail::tmat2x2<T, P> call(detail::tmat2x2<T, P> const & m)
200 {
201 detail::tmat2x2<T, P> result(detail::tmat2x2<T, P>::_null);
202 result[0][0] = m[0][0];
203 result[0][1] = m[1][0];
204 result[1][0] = m[0][1];
205 result[1][1] = m[1][1];
206 return result;
207 }
208 };
209
210 template <typename T, precision P>
211 struct compute_transpose<detail::tmat2x3, T, P>
212 {
213 GLM_FUNC_QUALIFIER static detail::tmat3x2<T, P> call(detail::tmat2x3<T, P> const & m)
214 {
215 detail::tmat3x2<T, P> result(detail::tmat3x2<T, P>::_null);
216 result[0][0] = m[0][0];
217 result[0][1] = m[1][0];
218 result[1][0] = m[0][1];
219 result[1][1] = m[1][1];
220 result[2][0] = m[0][2];
221 result[2][1] = m[1][2];
222 return result;
223 }
224 };
225
226 template <typename T, precision P>
227 struct compute_transpose<detail::tmat2x4, T, P>
228 {
229 GLM_FUNC_QUALIFIER static detail::tmat4x2<T, P> call(detail::tmat2x4<T, P> const & m)
230 {
231 detail::tmat4x2<T, P> result(detail::tmat4x2<T, P>::_null);
232 result[0][0] = m[0][0];
233 result[0][1] = m[1][0];
234 result[1][0] = m[0][1];
235 result[1][1] = m[1][1];
236 result[2][0] = m[0][2];
237 result[2][1] = m[1][2];
238 result[3][0] = m[0][3];
239 result[3][1] = m[1][3];
240 return result;
241 }
242 };
243
244 template <typename T, precision P>
245 struct compute_transpose<detail::tmat3x2, T, P>
246 {
247 GLM_FUNC_QUALIFIER static detail::tmat2x3<T, P> call(detail::tmat3x2<T, P> const & m)
248 {
249 detail::tmat2x3<T, P> result(detail::tmat2x3<T, P>::_null);
250 result[0][0] = m[0][0];
251 result[0][1] = m[1][0];
252 result[0][2] = m[2][0];
253 result[1][0] = m[0][1];
254 result[1][1] = m[1][1];
255 result[1][2] = m[2][1];
256 return result;
257 }
258 };
259
260 template <typename T, precision P>
261 struct compute_transpose<detail::tmat3x3, T, P>
262 {
263 GLM_FUNC_QUALIFIER static detail::tmat3x3<T, P> call(detail::tmat3x3<T, P> const & m)
264 {
265 detail::tmat3x3<T, P> result(detail::tmat3x3<T, P>::_null);
266 result[0][0] = m[0][0];
267 result[0][1] = m[1][0];
268 result[0][2] = m[2][0];
269
270 result[1][0] = m[0][1];
271 result[1][1] = m[1][1];
272 result[1][2] = m[2][1];
273
274 result[2][0] = m[0][2];
275 result[2][1] = m[1][2];
276 result[2][2] = m[2][2];
277 return result;
278 }
279 };
280
281 template <typename T, precision P>
282 struct compute_transpose<detail::tmat3x4, T, P>
283 {
284 GLM_FUNC_QUALIFIER static detail::tmat4x3<T, P> call(detail::tmat3x4<T, P> const & m)
285 {
286 detail::tmat4x3<T, P> result(detail::tmat4x3<T, P>::_null);
287 result[0][0] = m[0][0];
288 result[0][1] = m[1][0];
289 result[0][2] = m[2][0];
290 result[1][0] = m[0][1];
291 result[1][1] = m[1][1];
292 result[1][2] = m[2][1];
293 result[2][0] = m[0][2];
294 result[2][1] = m[1][2];
295 result[2][2] = m[2][2];
296 result[3][0] = m[0][3];
297 result[3][1] = m[1][3];
298 result[3][2] = m[2][3];
299 return result;
300 }
301 };
302
303 template <typename T, precision P>
304 struct compute_transpose<detail::tmat4x2, T, P>
305 {
306 GLM_FUNC_QUALIFIER static detail::tmat2x4<T, P> call(detail::tmat4x2<T, P> const & m)
307 {
308 detail::tmat2x4<T, P> result(detail::tmat2x4<T, P>::_null);
309 result[0][0] = m[0][0];
310 result[0][1] = m[1][0];
311 result[0][2] = m[2][0];
312 result[0][3] = m[3][0];
313 result[1][0] = m[0][1];
314 result[1][1] = m[1][1];
315 result[1][2] = m[2][1];
316 result[1][3] = m[3][1];
317 return result;
318 }
319 };
320
321 template <typename T, precision P>
322 struct compute_transpose<detail::tmat4x3, T, P>
323 {
324 GLM_FUNC_QUALIFIER static detail::tmat3x4<T, P> call(detail::tmat4x3<T, P> const & m)
325 {
326 detail::tmat3x4<T, P> result(detail::tmat3x4<T, P>::_null);
327 result[0][0] = m[0][0];
328 result[0][1] = m[1][0];
329 result[0][2] = m[2][0];
330 result[0][3] = m[3][0];
331 result[1][0] = m[0][1];
332 result[1][1] = m[1][1];
333 result[1][2] = m[2][1];
334 result[1][3] = m[3][1];
335 result[2][0] = m[0][2];
336 result[2][1] = m[1][2];
337 result[2][2] = m[2][2];
338 result[2][3] = m[3][2];
339 return result;
340 }
341 };
342
343 template <typename T, precision P>
344 struct compute_transpose<detail::tmat4x4, T, P>
345 {
346 GLM_FUNC_QUALIFIER static detail::tmat4x4<T, P> call(detail::tmat4x4<T, P> const & m)
347 {
348 detail::tmat4x4<T, P> result(detail::tmat4x4<T, P>::_null);
349 result[0][0] = m[0][0];
350 result[0][1] = m[1][0];
351 result[0][2] = m[2][0];
352 result[0][3] = m[3][0];
353
354 result[1][0] = m[0][1];
355 result[1][1] = m[1][1];
356 result[1][2] = m[2][1];
357 result[1][3] = m[3][1];
358
359 result[2][0] = m[0][2];
360 result[2][1] = m[1][2];
361 result[2][2] = m[2][2];
362 result[2][3] = m[3][2];
363
364 result[3][0] = m[0][3];
365 result[3][1] = m[1][3];
366 result[3][2] = m[2][3];
367 result[3][3] = m[3][3];
368 return result;
369 }
370 };
371
372 template <template <class, precision> class matType, typename T, precision P>
373 struct compute_determinant{};
374
375 template <typename T, precision P>
376 struct compute_determinant<detail::tmat2x2, T, P>
377 {
378 GLM_FUNC_QUALIFIER static T call(detail::tmat2x2<T, P> const & m)
379 {
380 return m[0][0] * m[1][1] - m[1][0] * m[0][1];
381 }
382 };
383
384 template <typename T, precision P>
385 struct compute_determinant<detail::tmat3x3, T, P>
386 {
387 GLM_FUNC_QUALIFIER static T call(detail::tmat3x3<T, P> const & m)
388 {
389 return
390 + m[0][0] * (m[1][1] * m[2][2] - m[2][1] * m[1][2])
391 - m[1][0] * (m[0][1] * m[2][2] - m[2][1] * m[0][2])
392 + m[2][0] * (m[0][1] * m[1][2] - m[1][1] * m[0][2]);
393 }
394 };
395
396 template <typename T, precision P>
397 struct compute_determinant<detail::tmat4x4, T, P>
398 {
399 GLM_FUNC_QUALIFIER static T call(detail::tmat4x4<T, P> const & m)
400 {
401 T SubFactor00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
402 T SubFactor01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
403 T SubFactor02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
404 T SubFactor03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
405 T SubFactor04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
406 T SubFactor05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
407
408 detail::tvec4<T, P> DetCof(
409 + (m[1][1] * SubFactor00 - m[1][2] * SubFactor01 + m[1][3] * SubFactor02),
410 - (m[1][0] * SubFactor00 - m[1][2] * SubFactor03 + m[1][3] * SubFactor04),
411 + (m[1][0] * SubFactor01 - m[1][1] * SubFactor03 + m[1][3] * SubFactor05),
412 - (m[1][0] * SubFactor02 - m[1][1] * SubFactor04 + m[1][2] * SubFactor05));
413
414 return
415 m[0][0] * DetCof[0] + m[0][1] * DetCof[1] +
416 m[0][2] * DetCof[2] + m[0][3] * DetCof[3];
417 }
418 };
419}//namespace detail
420
421 template <typename T, precision P, template <typename, precision> class matType>
422 GLM_FUNC_QUALIFIER matType<T, P> matrixCompMult(matType<T, P> const & x, matType<T, P> const & y)
423 {
424 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'matrixCompMult' only accept floating-point inputs");
425
426 matType<T, P> result(matType<T, P>::_null);
427 for(length_t i = 0; i < result.length(); ++i)
428 result[i] = x[i] * y[i];
429 return result;
430 }
431
432 template<typename T, precision P, template <typename, precision> class vecTypeA, template <typename, precision> class vecTypeB>
433 GLM_FUNC_QUALIFIER typename detail::outerProduct_trait<T, P, vecTypeA, vecTypeB>::type outerProduct(vecTypeA<T, P> const & c, vecTypeB<T, P> const & r)
434 {
435 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'outerProduct' only accept floating-point inputs");
436 return detail::compute_outerProduct<vecTypeA, vecTypeB, T, P>::call(c, r);
437 }
438
439 template <typename T, precision P, template <typename, precision> class matType>
440 GLM_FUNC_QUALIFIER typename matType<T, P>::transpose_type transpose(matType<T, P> const & m)
441 {
442 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'transpose' only accept floating-point inputs");
443 return detail::compute_transpose<matType, T, P>::call(m);
444 }
445
446 template <typename T, precision P, template <typename, precision> class matType>
447 GLM_FUNC_QUALIFIER T determinant(matType<T, P> const & m)
448 {
449 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'determinant' only accept floating-point inputs");
450 return detail::compute_determinant<matType, T, P>::call(m);
451 }
452
453 template <typename T, precision P, template <typename, precision> class matType>
454 GLM_FUNC_QUALIFIER matType<T, P> inverse(matType<T, P> const & m)
455 {
456 GLM_STATIC_ASSERT(std::numeric_limits<T>::is_iec559, "'inverse' only accept floating-point inputs");
457 return detail::compute_inverse<matType, T, P>::call(m);
458 }
459
460}//namespace glm