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/type_mat4x4.inl
     25 /// @date 2005-01-27 / 2011-06-15
     26 /// @author Christophe Riccio
     27 ///////////////////////////////////////////////////////////////////////////////////
     28 
     29 namespace glm{
     30 namespace detail
     31 {
     32 	template <typename T, precision P>
     33 	GLM_FUNC_QUALIFIER GLM_CONSTEXPR length_t tmat4x4<T, P>::length() const
     34 	{
     35 		return 4;
     36 	}
     37 
     38 	//////////////////////////////////////
     39 	// Accesses
     40 
     41 	template <typename T, precision P>
     42 	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type &
     43 	tmat4x4<T, P>::operator[]
     44 	(
     45 		length_t i
     46 	)
     47 	{
     48 		assert(i < this->length());
     49 		return this->value[i];
     50 	}
     51 
     52 	template <typename T, precision P>
     53 	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type const &
     54 	tmat4x4<T, P>::operator[]
     55 	(
     56 		length_t i
     57 	) const
     58 	{
     59 		assert(i < this->length());
     60 		return this->value[i];
     61 	}
     62 
     63 	//////////////////////////////////////////////////////////////
     64 	// Constructors
     65 
     66 	template <typename T, precision P>
     67 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4()
     68 	{
     69 		T Zero(0);
     70 		T One(1);
     71 		this->value[0] = col_type(One, Zero, Zero, Zero);
     72 		this->value[1] = col_type(Zero, One, Zero, Zero);
     73 		this->value[2] = col_type(Zero, Zero, One, Zero);
     74 		this->value[3] = col_type(Zero, Zero, Zero, One);
     75 	}
     76 	
     77 	template <typename T, precision P>
     78 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
     79 	(
     80 		tmat4x4<T, P> const & m
     81 	)
     82 	{
     83 		this->value[0] = m[0];
     84 		this->value[1] = m[1];
     85 		this->value[2] = m[2];
     86 		this->value[3] = m[3];
     87 	}
     88 
     89 	template <typename T, precision P>
     90 	template <precision Q>
     91 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
     92 	(
     93 		tmat4x4<T, Q> const & m
     94 	)
     95 	{
     96 		this->value[0] = m[0];
     97 		this->value[1] = m[1];
     98 		this->value[2] = m[2];
     99 		this->value[3] = m[3];
    100 	}
    101 
    102 	template <typename T, precision P>
    103 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    104 	(
    105 		ctor
    106 	)
    107 	{}
    108 
    109 	template <typename T, precision P>
    110 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    111 	(
    112 		T const & s
    113 	)
    114 	{
    115 		value_type const Zero(0);
    116 		this->value[0] = col_type(s, Zero, Zero, Zero);
    117 		this->value[1] = col_type(Zero, s, Zero, Zero);
    118 		this->value[2] = col_type(Zero, Zero, s, Zero);
    119 		this->value[3] = col_type(Zero, Zero, Zero, s);
    120 	}
    121 
    122 	template <typename T, precision P>
    123 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    124 	(
    125 		T const & x0, T const & y0, T const & z0, T const & w0,
    126 		T const & x1, T const & y1, T const & z1, T const & w1,
    127 		T const & x2, T const & y2, T const & z2, T const & w2,
    128 		T const & x3, T const & y3, T const & z3, T const & w3
    129 	)
    130 	{
    131 		this->value[0] = col_type(x0, y0, z0, w0);
    132 		this->value[1] = col_type(x1, y1, z1, w1);
    133 		this->value[2] = col_type(x2, y2, z2, w2);
    134 		this->value[3] = col_type(x3, y3, z3, w3);
    135 	}
    136 
    137 	template <typename T, precision P>
    138 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    139 	(
    140 		col_type const & v0,
    141 		col_type const & v1,
    142 		col_type const & v2,
    143 		col_type const & v3
    144 	)
    145 	{
    146 		this->value[0] = v0;
    147 		this->value[1] = v1;
    148 		this->value[2] = v2;
    149 		this->value[3] = v3;
    150 	}
    151 
    152 	template <typename T, precision P>
    153 	template <typename U, precision Q>
    154 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    155 	(
    156 		tmat4x4<U, Q> const & m
    157 	)
    158 	{
    159 		this->value[0] = col_type(m[0]);
    160 		this->value[1] = col_type(m[1]);
    161 		this->value[2] = col_type(m[2]);
    162 		this->value[3] = col_type(m[3]);
    163 	}
    164 
    165 	//////////////////////////////////////
    166 	// Conversion constructors
    167 	template <typename T, precision P> 
    168 	template <
    169 		typename X1, typename Y1, typename Z1, typename W1,
    170 		typename X2, typename Y2, typename Z2, typename W2,
    171 		typename X3, typename Y3, typename Z3, typename W3,
    172 		typename X4, typename Y4, typename Z4, typename W4>
    173 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    174 	(
    175 		X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1,
    176 		X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2,
    177 		X3 const & x3, Y3 const & y3, Z3 const & z3, W3 const & w3,
    178 		X4 const & x4, Y4 const & y4, Z4 const & z4, W4 const & w4
    179 	)
    180 	{
    181 		GLM_STATIC_ASSERT(std::numeric_limits<X1>::is_iec559 || std::numeric_limits<X1>::is_integer, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid.");
    182 		GLM_STATIC_ASSERT(std::numeric_limits<Y1>::is_iec559 || std::numeric_limits<Y1>::is_integer, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid.");
    183 		GLM_STATIC_ASSERT(std::numeric_limits<Z1>::is_iec559 || std::numeric_limits<Z1>::is_integer, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid.");
    184 		GLM_STATIC_ASSERT(std::numeric_limits<W1>::is_iec559 || std::numeric_limits<W1>::is_integer, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid.");
    185 
    186 		GLM_STATIC_ASSERT(std::numeric_limits<X2>::is_iec559 || std::numeric_limits<X2>::is_integer, "*mat4x4 constructor only takes float and integer types, 5th parameter type invalid.");
    187 		GLM_STATIC_ASSERT(std::numeric_limits<Y2>::is_iec559 || std::numeric_limits<Y2>::is_integer, "*mat4x4 constructor only takes float and integer types, 6th parameter type invalid.");
    188 		GLM_STATIC_ASSERT(std::numeric_limits<Z2>::is_iec559 || std::numeric_limits<Z2>::is_integer, "*mat4x4 constructor only takes float and integer types, 7th parameter type invalid.");
    189 		GLM_STATIC_ASSERT(std::numeric_limits<W2>::is_iec559 || std::numeric_limits<W2>::is_integer, "*mat4x4 constructor only takes float and integer types, 8th parameter type invalid.");
    190 
    191 		GLM_STATIC_ASSERT(std::numeric_limits<X3>::is_iec559 || std::numeric_limits<X3>::is_integer, "*mat4x4 constructor only takes float and integer types, 9th parameter type invalid.");
    192 		GLM_STATIC_ASSERT(std::numeric_limits<Y3>::is_iec559 || std::numeric_limits<Y3>::is_integer, "*mat4x4 constructor only takes float and integer types, 10th parameter type invalid.");
    193 		GLM_STATIC_ASSERT(std::numeric_limits<Z3>::is_iec559 || std::numeric_limits<Z3>::is_integer, "*mat4x4 constructor only takes float and integer types, 11th parameter type invalid.");
    194 		GLM_STATIC_ASSERT(std::numeric_limits<W3>::is_iec559 || std::numeric_limits<W3>::is_integer, "*mat4x4 constructor only takes float and integer types, 12th parameter type invalid.");
    195 
    196 		GLM_STATIC_ASSERT(std::numeric_limits<X4>::is_iec559 || std::numeric_limits<X4>::is_integer, "*mat4x4 constructor only takes float and integer types, 13th parameter type invalid.");
    197 		GLM_STATIC_ASSERT(std::numeric_limits<Y4>::is_iec559 || std::numeric_limits<Y4>::is_integer, "*mat4x4 constructor only takes float and integer types, 14th parameter type invalid.");
    198 		GLM_STATIC_ASSERT(std::numeric_limits<Z4>::is_iec559 || std::numeric_limits<Z4>::is_integer, "*mat4x4 constructor only takes float and integer types, 15th parameter type invalid.");
    199 		GLM_STATIC_ASSERT(std::numeric_limits<W4>::is_iec559 || std::numeric_limits<W4>::is_integer, "*mat4x4 constructor only takes float and integer types, 16th parameter type invalid.");
    200 
    201 		this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1), value_type(w1));
    202 		this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2), value_type(w2));
    203 		this->value[2] = col_type(static_cast<T>(x3), value_type(y3), value_type(z3), value_type(w3));
    204 		this->value[3] = col_type(static_cast<T>(x4), value_type(y4), value_type(z4), value_type(w4));
    205 	}
    206 	
    207 	template <typename T, precision P>
    208 	template <typename V1, typename V2, typename V3, typename V4>
    209 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    210 	(
    211 		tvec4<V1, P> const & v1,
    212 		tvec4<V2, P> const & v2,
    213 		tvec4<V3, P> const & v3,
    214 		tvec4<V4, P> const & v4
    215 	)		
    216 	{
    217 		GLM_STATIC_ASSERT(std::numeric_limits<V1>::is_iec559 || std::numeric_limits<V1>::is_integer, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid.");
    218 		GLM_STATIC_ASSERT(std::numeric_limits<V2>::is_iec559 || std::numeric_limits<V2>::is_integer, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid.");
    219 		GLM_STATIC_ASSERT(std::numeric_limits<V3>::is_iec559 || std::numeric_limits<V3>::is_integer, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid.");
    220 		GLM_STATIC_ASSERT(std::numeric_limits<V4>::is_iec559 || std::numeric_limits<V4>::is_integer, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid.");
    221 
    222 		this->value[0] = col_type(v1);
    223 		this->value[1] = col_type(v2);
    224 		this->value[2] = col_type(v3);
    225 		this->value[3] = col_type(v4);
    226 	}
    227 
    228 	//////////////////////////////////////
    229 	// Matrix convertion constructors
    230 	template <typename T, precision P>
    231 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    232 	(
    233 		tmat2x2<T, P> const & m
    234 	)
    235 	{
    236 		this->value[0] = col_type(m[0], detail::tvec2<T, P>(0));
    237 		this->value[1] = col_type(m[1], detail::tvec2<T, P>(0));
    238 		this->value[2] = col_type(static_cast<T>(0));
    239 		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
    240 	}
    241 
    242 	template <typename T, precision P>
    243 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    244 	(
    245 		tmat3x3<T, P> const & m
    246 	)
    247 	{
    248 		this->value[0] = col_type(m[0], value_type(0));
    249 		this->value[1] = col_type(m[1], value_type(0));
    250 		this->value[2] = col_type(m[2], value_type(0));
    251 		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
    252 	}
    253 
    254 	template <typename T, precision P>
    255 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    256 	(
    257 		tmat2x3<T, P> const & m
    258 	)
    259 	{
    260 		this->value[0] = col_type(m[0], value_type(0));
    261 		this->value[1] = col_type(m[1], value_type(0));
    262 		this->value[2] = col_type(static_cast<T>(0));
    263 		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
    264 	}
    265 
    266 	template <typename T, precision P>
    267 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    268 	(
    269 		tmat3x2<T, P> const & m
    270 	)
    271 	{
    272 		this->value[0] = col_type(m[0], detail::tvec2<T, P>(0));
    273 		this->value[1] = col_type(m[1], detail::tvec2<T, P>(0));
    274 		this->value[2] = col_type(m[2], detail::tvec2<T, P>(0));
    275 		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
    276 	}
    277 
    278 	template <typename T, precision P>
    279 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    280 	(
    281 		tmat2x4<T, P> const & m
    282 	)
    283 	{
    284 		this->value[0] = m[0];
    285 		this->value[1] = m[1];
    286 		this->value[2] = col_type(T(0));
    287 		this->value[3] = col_type(T(0), T(0), T(0), T(1));
    288 	}
    289 
    290 	template <typename T, precision P>
    291 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    292 	(
    293 		tmat4x2<T, P> const & m
    294 	)
    295 	{
    296 		this->value[0] = col_type(m[0], detail::tvec2<T, P>(0));
    297 		this->value[1] = col_type(m[1], detail::tvec2<T, P>(0));
    298 		this->value[2] = col_type(T(0));
    299 		this->value[3] = col_type(T(0), T(0), T(0), T(1));
    300 	}
    301 
    302 	template <typename T, precision P>
    303 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    304 	(
    305 		tmat3x4<T, P> const & m
    306 	)
    307 	{
    308 		this->value[0] = m[0];
    309 		this->value[1] = m[1];
    310 		this->value[2] = m[2];
    311 		this->value[3] = col_type(T(0), T(0), T(0), T(1));
    312 	}
    313 
    314 	template <typename T, precision P>
    315 	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
    316 	(
    317 		tmat4x3<T, P> const & m
    318 	)
    319 	{
    320 		this->value[0] = col_type(m[0], T(0));
    321 		this->value[1] = col_type(m[1], T(0));
    322 		this->value[2] = col_type(m[2], T(0));
    323 		this->value[3] = col_type(m[3], T(1));
    324 	}
    325 
    326 	//////////////////////////////////////////////////////////////
    327 	// Operators
    328 
    329 	template <typename T, precision P>
    330 	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator=
    331 	(
    332 		tmat4x4<T, P> const & m
    333 	)
    334 	{
    335 		//memcpy could be faster
    336 		//memcpy(&this->value, &m.value, 16 * sizeof(valType));
    337 		this->value[0] = m[0];
    338 		this->value[1] = m[1];
    339 		this->value[2] = m[2];
    340 		this->value[3] = m[3];
    341 		return *this;
    342 	}
    343 
    344 	template <typename T, precision P> 
    345 	template <typename U> 
    346 	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator=
    347 	(
    348 		tmat4x4<U, P> const & m
    349 	)
    350 	{
    351 		//memcpy could be faster
    352 		//memcpy(&this->value, &m.value, 16 * sizeof(valType));
    353 		this->value[0] = m[0];
    354 		this->value[1] = m[1];
    355 		this->value[2] = m[2];
    356 		this->value[3] = m[3];
    357 		return *this;
    358 	}
    359 
    360 	template <typename T, precision P>
    361 	template <typename U>
    362 	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator+= (U s)
    363 	{
    364 		this->value[0] += s;
    365 		this->value[1] += s;
    366 		this->value[2] += s;
    367 		this->value[3] += s;
    368 		return *this;
    369 	}
    370 
    371 	template <typename T, precision P>
    372 	template <typename U>
    373 	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator+= (tmat4x4<U, P> const & m)
    374 	{
    375 		this->value[0] += m[0];
    376 		this->value[1] += m[1];
    377 		this->value[2] += m[2];
    378 		this->value[3] += m[3];
    379 		return *this;
    380 	}
    381 
    382 	template <typename T, precision P>
    383 	template <typename U>
    384 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-= (U s)
    385 	{
    386 		this->value[0] -= s;
    387 		this->value[1] -= s;
    388 		this->value[2] -= s;
    389 		this->value[3] -= s;
    390 		return *this;
    391 	}
    392 
    393 	template <typename T, precision P>
    394 	template <typename U>
    395 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-= (tmat4x4<U, P> const & m)
    396 	{
    397 		this->value[0] -= m[0];
    398 		this->value[1] -= m[1];
    399 		this->value[2] -= m[2];
    400 		this->value[3] -= m[3];
    401 		return *this;
    402 	}
    403 
    404 	template <typename T, precision P>
    405 	template <typename U>
    406 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator*= (U s)
    407 	{
    408 		this->value[0] *= s;
    409 		this->value[1] *= s;
    410 		this->value[2] *= s;
    411 		this->value[3] *= s;
    412 		return *this;
    413 	}
    414 
    415 	template <typename T, precision P>
    416 	template <typename U>
    417 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator*= (tmat4x4<U, P> const & m)
    418 	{
    419 		return (*this = *this * m);
    420 	}
    421 
    422 	template <typename T, precision P>
    423 	template <typename U>
    424 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator/= (U s)
    425 	{
    426 		this->value[0] /= s;
    427 		this->value[1] /= s;
    428 		this->value[2] /= s;
    429 		this->value[3] /= s;
    430 		return *this;
    431 	}
    432 
    433 	template <typename T, precision P>
    434 	template <typename U>
    435 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator/= (tmat4x4<U, P> const & m)
    436 	{
    437 		return (*this = *this * detail::compute_inverse<detail::tmat4x4, T, P>::call(m));
    438 	}
    439 
    440 	template <typename T, precision P>
    441 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator++ ()
    442 	{
    443 		++this->value[0];
    444 		++this->value[1];
    445 		++this->value[2];
    446 		++this->value[3];
    447 		return *this;
    448 	}
    449 
    450 	template <typename T, precision P>
    451 	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-- ()
    452 	{
    453 		--this->value[0];
    454 		--this->value[1];
    455 		--this->value[2];
    456 		--this->value[3];
    457 		return *this;
    458 	}
    459 
    460 	template <typename T, precision P>
    461 	GLM_FUNC_QUALIFIER tmat4x4<T, P> tmat4x4<T, P>::operator++(int)
    462 	{
    463 		tmat4x4<T, P> Result(*this);
    464 		++*this;
    465 		return Result;
    466 	}
    467 
    468 	template <typename T, precision P>
    469 	GLM_FUNC_QUALIFIER tmat4x4<T, P> tmat4x4<T, P>::operator--(int)
    470 	{
    471 		tmat4x4<T, P> Result(*this);
    472 		--*this;
    473 		return Result;
    474 	}
    475 
    476 	template <typename T, precision P>
    477 	struct compute_inverse<detail::tmat4x4, T, P>
    478 	{
    479 		static detail::tmat4x4<T, P> call(detail::tmat4x4<T, P> const & m)
    480 		{
    481 			T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
    482 			T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
    483 			T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
    484 
    485 			T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
    486 			T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
    487 			T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
    488 
    489 			T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
    490 			T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
    491 			T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
    492 
    493 			T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
    494 			T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
    495 			T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
    496 
    497 			T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
    498 			T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
    499 			T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
    500 
    501 			T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
    502 			T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
    503 			T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
    504 
    505 			detail::tvec4<T, P> Fac0(Coef00, Coef00, Coef02, Coef03);
    506 			detail::tvec4<T, P> Fac1(Coef04, Coef04, Coef06, Coef07);
    507 			detail::tvec4<T, P> Fac2(Coef08, Coef08, Coef10, Coef11);
    508 			detail::tvec4<T, P> Fac3(Coef12, Coef12, Coef14, Coef15);
    509 			detail::tvec4<T, P> Fac4(Coef16, Coef16, Coef18, Coef19);
    510 			detail::tvec4<T, P> Fac5(Coef20, Coef20, Coef22, Coef23);
    511 
    512 			detail::tvec4<T, P> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]);
    513 			detail::tvec4<T, P> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]);
    514 			detail::tvec4<T, P> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]);
    515 			detail::tvec4<T, P> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]);
    516 
    517 			detail::tvec4<T, P> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2);
    518 			detail::tvec4<T, P> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4);
    519 			detail::tvec4<T, P> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5);
    520 			detail::tvec4<T, P> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5);
    521 
    522 			detail::tvec4<T, P> SignA(+1, -1, +1, -1);
    523 			detail::tvec4<T, P> SignB(-1, +1, -1, +1);
    524 			detail::tmat4x4<T, P> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB);
    525 
    526 			detail::tvec4<T, P> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]);
    527 
    528 			detail::tvec4<T, P> Dot0(m[0] * Row0);
    529 			T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w);
    530 
    531 			T OneOverDeterminant = static_cast<T>(1) / Dot1;
    532 
    533 			return Inverse * OneOverDeterminant;
    534 		}
    535 	};
    536 
    537 	// Binary operators
    538 	template <typename T, precision P>
    539 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+
    540 	(
    541 		tmat4x4<T, P> const & m,
    542 		T const & s
    543 	)
    544 	{
    545 		return tmat4x4<T, P>(
    546 			m[0] + s,
    547 			m[1] + s,
    548 			m[2] + s,
    549 			m[3] + s);
    550 	}
    551 
    552 	template <typename T, precision P>
    553 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+
    554 	(
    555 		T const & s,
    556 		tmat4x4<T, P> const & m
    557 	)
    558 	{
    559 		return tmat4x4<T, P>(
    560 			m[0] + s,
    561 			m[1] + s,
    562 			m[2] + s,
    563 			m[3] + s);
    564 	}
    565 
    566 	template <typename T, precision P>
    567 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+
    568 	(
    569 		tmat4x4<T, P> const & m1,
    570 		tmat4x4<T, P> const & m2
    571 	)
    572 	{
    573 		return tmat4x4<T, P>(
    574 			m1[0] + m2[0],
    575 			m1[1] + m2[1],
    576 			m1[2] + m2[2],
    577 			m1[3] + m2[3]);
    578 	}
    579 
    580 	template <typename T, precision P>
    581 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-
    582 	(
    583 		tmat4x4<T, P> const & m,
    584 		T const & s
    585 	)
    586 	{
    587 		return tmat4x4<T, P>(
    588 			m[0] - s,
    589 			m[1] - s,
    590 			m[2] - s,
    591 			m[3] - s);
    592 	}
    593 
    594 	template <typename T, precision P>
    595 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-
    596 	(
    597 		T const & s,
    598 		tmat4x4<T, P> const & m
    599 	)
    600 	{
    601 		return tmat4x4<T, P>(
    602 			s - m[0],
    603 			s - m[1],
    604 			s - m[2],
    605 			s - m[3]);
    606 	}
    607 
    608 	template <typename T, precision P>
    609 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-
    610 	(
    611 		tmat4x4<T, P> const & m1,
    612 		tmat4x4<T, P> const & m2
    613 	)
    614 	{
    615 		return tmat4x4<T, P>(
    616 			m1[0] - m2[0],
    617 			m1[1] - m2[1],
    618 			m1[2] - m2[2],
    619 			m1[3] - m2[3]);
    620 	}
    621 
    622 	template <typename T, precision P>
    623 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*
    624 	(
    625 		tmat4x4<T, P> const & m,
    626 		T const  & s
    627 	)
    628 	{
    629 		return tmat4x4<T, P>(
    630 			m[0] * s,
    631 			m[1] * s,
    632 			m[2] * s,
    633 			m[3] * s);
    634 	}
    635 
    636 	template <typename T, precision P>
    637 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*
    638 	(
    639 		T const & s,
    640 		tmat4x4<T, P> const & m
    641 	)
    642 	{
    643 		return tmat4x4<T, P>(
    644 			m[0] * s,
    645 			m[1] * s,
    646 			m[2] * s,
    647 			m[3] * s);
    648 	}
    649 
    650 	template <typename T, precision P>
    651 	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type operator*
    652 	(
    653 		tmat4x4<T, P> const & m,
    654 		typename tmat4x4<T, P>::row_type const & v
    655 	)
    656 	{
    657 /*
    658 		__m128 v0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(0, 0, 0, 0));
    659 		__m128 v1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(1, 1, 1, 1));
    660 		__m128 v2 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(2, 2, 2, 2));
    661 		__m128 v3 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 3, 3, 3));
    662 
    663 		__m128 m0 = _mm_mul_ps(m[0].data, v0);
    664 		__m128 m1 = _mm_mul_ps(m[1].data, v1);
    665 		__m128 a0 = _mm_add_ps(m0, m1);
    666 
    667 		__m128 m2 = _mm_mul_ps(m[2].data, v2);
    668 		__m128 m3 = _mm_mul_ps(m[3].data, v3);
    669 		__m128 a1 = _mm_add_ps(m2, m3);
    670 
    671 		__m128 a2 = _mm_add_ps(a0, a1);
    672 
    673 		return typename tmat4x4<T, P>::col_type(a2);
    674 */
    675 
    676 		typename tmat4x4<T, P>::col_type const Mov0(v[0]);
    677 		typename tmat4x4<T, P>::col_type const Mov1(v[1]);
    678 		typename tmat4x4<T, P>::col_type const Mul0 = m[0] * Mov0;
    679 		typename tmat4x4<T, P>::col_type const Mul1 = m[1] * Mov1;
    680 		typename tmat4x4<T, P>::col_type const Add0 = Mul0 + Mul1;
    681 		typename tmat4x4<T, P>::col_type const Mov2(v[2]);
    682 		typename tmat4x4<T, P>::col_type const Mov3(v[3]);
    683 		typename tmat4x4<T, P>::col_type const Mul2 = m[2] * Mov2;
    684 		typename tmat4x4<T, P>::col_type const Mul3 = m[3] * Mov3;
    685 		typename tmat4x4<T, P>::col_type const Add1 = Mul2 + Mul3;
    686 		typename tmat4x4<T, P>::col_type const Add2 = Add0 + Add1;
    687 		return Add2;
    688 
    689 /*
    690 		return typename tmat4x4<T, P>::col_type(
    691 			m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3],
    692 			m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3],
    693 			m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3],
    694 			m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]);
    695 */
    696 	}
    697 
    698 	template <typename T, precision P>
    699 	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::row_type operator*
    700 	(
    701 		typename tmat4x4<T, P>::col_type const & v,
    702 		tmat4x4<T, P> const & m
    703 	)
    704 	{
    705 		return typename tmat4x4<T, P>::row_type(
    706 			m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3],
    707 			m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3],
    708 			m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3],
    709 			m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]);
    710 	}
    711 
    712 	template <typename T, precision P>
    713 	GLM_FUNC_QUALIFIER tmat2x4<T, P> operator*
    714 	(
    715 		tmat4x4<T, P> const & m1,
    716 		tmat2x4<T, P> const & m2
    717 	)
    718 	{
    719 		return tmat2x4<T, P>(
    720 			m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3],
    721 			m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3],
    722 			m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3],
    723 			m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3],
    724 			m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3],
    725 			m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3],
    726 			m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3],
    727 			m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3]);
    728 	}
    729 
    730 	template <typename T, precision P>
    731 	GLM_FUNC_QUALIFIER tmat3x4<T, P> operator*
    732 	(
    733 		tmat4x4<T, P> const & m1,
    734 		tmat3x4<T, P> const & m2
    735 	)
    736 	{
    737 		return tmat3x4<T, P>(
    738 			m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3],
    739 			m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3],
    740 			m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3],
    741 			m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3],
    742 			m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3],
    743 			m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3],
    744 			m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3],
    745 			m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3],
    746 			m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3],
    747 			m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3],
    748 			m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3],
    749 			m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2] + m1[3][3] * m2[2][3]);
    750 	}
    751 
    752 	template <typename T, precision P>
    753 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*
    754 	(
    755 		tmat4x4<T, P> const & m1,
    756 		tmat4x4<T, P> const & m2
    757 	)
    758 	{
    759 		typename tmat4x4<T, P>::col_type const SrcA0 = m1[0];
    760 		typename tmat4x4<T, P>::col_type const SrcA1 = m1[1];
    761 		typename tmat4x4<T, P>::col_type const SrcA2 = m1[2];
    762 		typename tmat4x4<T, P>::col_type const SrcA3 = m1[3];
    763 
    764 		typename tmat4x4<T, P>::col_type const SrcB0 = m2[0];
    765 		typename tmat4x4<T, P>::col_type const SrcB1 = m2[1];
    766 		typename tmat4x4<T, P>::col_type const SrcB2 = m2[2];
    767 		typename tmat4x4<T, P>::col_type const SrcB3 = m2[3];
    768 
    769 		tmat4x4<T, P> Result(tmat4x4<T, P>::_null);
    770 		Result[0] = SrcA0 * SrcB0[0] + SrcA1 * SrcB0[1] + SrcA2 * SrcB0[2] + SrcA3 * SrcB0[3];
    771 		Result[1] = SrcA0 * SrcB1[0] + SrcA1 * SrcB1[1] + SrcA2 * SrcB1[2] + SrcA3 * SrcB1[3];
    772 		Result[2] = SrcA0 * SrcB2[0] + SrcA1 * SrcB2[1] + SrcA2 * SrcB2[2] + SrcA3 * SrcB2[3];
    773 		Result[3] = SrcA0 * SrcB3[0] + SrcA1 * SrcB3[1] + SrcA2 * SrcB3[2] + SrcA3 * SrcB3[3];
    774 		return Result;
    775 	}
    776 
    777 	template <typename T, precision P>
    778 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/
    779 	(
    780 		tmat4x4<T, P> const & m,
    781 		T const & s
    782 	)
    783 	{
    784 		return tmat4x4<T, P>(
    785 			m[0] / s,
    786 			m[1] / s,
    787 			m[2] / s,
    788 			m[3] / s);
    789 	}
    790 
    791 	template <typename T, precision P>
    792 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/
    793 	(
    794 		T const & s,
    795 		tmat4x4<T, P> const & m
    796 	)
    797 	{
    798 		return tmat4x4<T, P>(
    799 			s / m[0],
    800 			s / m[1],
    801 			s / m[2],
    802 			s / m[3]);
    803 	}
    804 
    805 	template <typename T, precision P>
    806 	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type operator/
    807 	(
    808 		tmat4x4<T, P> const & m,
    809 		typename tmat4x4<T, P>::row_type const & v
    810 	)
    811 	{
    812 		return detail::compute_inverse<detail::tmat4x4, T, P>::call(m) * v;
    813 	}
    814 
    815 	template <typename T, precision P>
    816 	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::row_type operator/
    817 	(
    818 		typename tmat4x4<T, P>::col_type const & v,
    819 		tmat4x4<T, P> const & m
    820 	)
    821 	{
    822 		return v * detail::compute_inverse<detail::tmat4x4, T, P>::call(m);
    823 	}
    824 
    825 	template <typename T, precision P>
    826 	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/
    827 	(
    828 		tmat4x4<T, P> const & m1,
    829 		tmat4x4<T, P> const & m2
    830 	)
    831 	{
    832 		tmat4x4<T, P> m1_copy(m1);
    833 		return m1_copy /= m2;
    834 	}
    835 
    836 	// Unary constant operators
    837 	template <typename T, precision P>
    838 	GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator-
    839 	(
    840 		tmat4x4<T, P> const & m
    841 	)
    842 	{
    843 		return tmat4x4<T, P>(
    844 			-m[0],
    845 			-m[1],
    846 			-m[2],
    847 			-m[3]);
    848 	}
    849 
    850 	template <typename T, precision P> 
    851 	GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator++
    852 	(
    853 		tmat4x4<T, P> const & m,
    854 		int
    855 	)
    856 	{
    857 		return tmat4x4<T, P>(
    858 			m[0] + static_cast<T>(1),
    859 			m[1] + static_cast<T>(1),
    860 			m[2] + static_cast<T>(1),
    861 			m[3] + static_cast<T>(1));
    862 	}
    863 
    864 	template <typename T, precision P>
    865 	GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator--
    866 	(
    867 		tmat4x4<T, P> const & m,
    868 		int
    869 	)
    870 	{
    871 		return tmat4x4<T, P>(
    872 			m[0] - static_cast<T>(1),
    873 			m[1] - static_cast<T>(1),
    874 			m[2] - static_cast<T>(1),
    875 			m[3] - static_cast<T>(1));
    876 	}
    877 
    878 	//////////////////////////////////////
    879 	// Boolean operators
    880 
    881 	template <typename T, precision P>
    882 	GLM_FUNC_QUALIFIER bool operator==
    883 	(
    884 		tmat4x4<T, P> const & m1,
    885 		tmat4x4<T, P> const & m2
    886 	)
    887 	{
    888 		return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]);
    889 	}
    890 
    891 	template <typename T, precision P>
    892 	GLM_FUNC_QUALIFIER bool operator!=
    893 	(
    894 		tmat4x4<T, P> const & m1,
    895 		tmat4x4<T, P> const & m2
    896 	)
    897 	{
    898 		return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]);
    899 	}
    900 
    901 } //namespace detail
    902 } //namespace glm
    903