Home | History | Annotate | Download | only in detail
      1 ///////////////////////////////////////////////////////////////////////////////////
      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 
     32 namespace glm{
     33 namespace 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
    461