1 /////////////////////////////////////////////////////////////////////////////////////////////////// 2 // OpenGL Mathematics Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net) 3 /////////////////////////////////////////////////////////////////////////////////////////////////// 4 // Created : 2009-05-19 5 // Updated : 2009-05-19 6 // Licence : This source is under MIT License 7 // File : glm/gtx/simd_mat4.hpp 8 /////////////////////////////////////////////////////////////////////////////////////////////////// 9 10 namespace glm{ 11 namespace detail{ 12 13 GLM_FUNC_QUALIFIER length_t fmat4x4SIMD::length() const 14 { 15 return 4; 16 } 17 18 ////////////////////////////////////// 19 // Accesses 20 21 GLM_FUNC_QUALIFIER fvec4SIMD & fmat4x4SIMD::operator[] 22 ( 23 length_t i 24 ) 25 { 26 assert(i < this->length()); 27 28 return this->Data[i]; 29 } 30 31 GLM_FUNC_QUALIFIER fvec4SIMD const & fmat4x4SIMD::operator[] 32 ( 33 length_t i 34 ) const 35 { 36 assert(i < this->length()); 37 38 return this->Data[i]; 39 } 40 41 ////////////////////////////////////////////////////////////// 42 // Constructors 43 44 GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD() 45 { 46 #ifndef GLM_SIMD_ENABLE_DEFAULT_INIT 47 this->Data[0] = fvec4SIMD(1.0f, 0, 0, 0); 48 this->Data[1] = fvec4SIMD(0, 1.0f, 0, 0); 49 this->Data[2] = fvec4SIMD(0, 0, 1.0f, 0); 50 this->Data[3] = fvec4SIMD(0, 0, 0, 1.0f); 51 #endif 52 } 53 54 GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD(float const & s) 55 { 56 this->Data[0] = fvec4SIMD(s, 0, 0, 0); 57 this->Data[1] = fvec4SIMD(0, s, 0, 0); 58 this->Data[2] = fvec4SIMD(0, 0, s, 0); 59 this->Data[3] = fvec4SIMD(0, 0, 0, s); 60 } 61 62 GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD 63 ( 64 float const & x0, float const & y0, float const & z0, float const & w0, 65 float const & x1, float const & y1, float const & z1, float const & w1, 66 float const & x2, float const & y2, float const & z2, float const & w2, 67 float const & x3, float const & y3, float const & z3, float const & w3 68 ) 69 { 70 this->Data[0] = fvec4SIMD(x0, y0, z0, w0); 71 this->Data[1] = fvec4SIMD(x1, y1, z1, w1); 72 this->Data[2] = fvec4SIMD(x2, y2, z2, w2); 73 this->Data[3] = fvec4SIMD(x3, y3, z3, w3); 74 } 75 76 GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD 77 ( 78 fvec4SIMD const & v0, 79 fvec4SIMD const & v1, 80 fvec4SIMD const & v2, 81 fvec4SIMD const & v3 82 ) 83 { 84 this->Data[0] = v0; 85 this->Data[1] = v1; 86 this->Data[2] = v2; 87 this->Data[3] = v3; 88 } 89 90 GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD 91 ( 92 mat4 const & m 93 ) 94 { 95 this->Data[0] = fvec4SIMD(m[0]); 96 this->Data[1] = fvec4SIMD(m[1]); 97 this->Data[2] = fvec4SIMD(m[2]); 98 this->Data[3] = fvec4SIMD(m[3]); 99 } 100 101 GLM_FUNC_QUALIFIER fmat4x4SIMD::fmat4x4SIMD 102 ( 103 __m128 const in[4] 104 ) 105 { 106 this->Data[0] = in[0]; 107 this->Data[1] = in[1]; 108 this->Data[2] = in[2]; 109 this->Data[3] = in[3]; 110 } 111 112 ////////////////////////////////////////////////////////////// 113 // mat4 operators 114 115 GLM_FUNC_QUALIFIER fmat4x4SIMD& fmat4x4SIMD::operator= 116 ( 117 fmat4x4SIMD const & m 118 ) 119 { 120 this->Data[0] = m[0]; 121 this->Data[1] = m[1]; 122 this->Data[2] = m[2]; 123 this->Data[3] = m[3]; 124 return *this; 125 } 126 127 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator+= 128 ( 129 fmat4x4SIMD const & m 130 ) 131 { 132 this->Data[0].Data = _mm_add_ps(this->Data[0].Data, m[0].Data); 133 this->Data[1].Data = _mm_add_ps(this->Data[1].Data, m[1].Data); 134 this->Data[2].Data = _mm_add_ps(this->Data[2].Data, m[2].Data); 135 this->Data[3].Data = _mm_add_ps(this->Data[3].Data, m[3].Data); 136 return *this; 137 } 138 139 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator-= 140 ( 141 fmat4x4SIMD const & m 142 ) 143 { 144 this->Data[0].Data = _mm_sub_ps(this->Data[0].Data, m[0].Data); 145 this->Data[1].Data = _mm_sub_ps(this->Data[1].Data, m[1].Data); 146 this->Data[2].Data = _mm_sub_ps(this->Data[2].Data, m[2].Data); 147 this->Data[3].Data = _mm_sub_ps(this->Data[3].Data, m[3].Data); 148 149 return *this; 150 } 151 152 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator*= 153 ( 154 fmat4x4SIMD const & m 155 ) 156 { 157 sse_mul_ps(&this->Data[0].Data, &m.Data[0].Data, &this->Data[0].Data); 158 return *this; 159 } 160 161 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator/= 162 ( 163 fmat4x4SIMD const & m 164 ) 165 { 166 __m128 Inv[4]; 167 sse_inverse_ps(&m.Data[0].Data, Inv); 168 sse_mul_ps(&this->Data[0].Data, Inv, &this->Data[0].Data); 169 return *this; 170 } 171 172 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator+= 173 ( 174 float const & s 175 ) 176 { 177 __m128 Operand = _mm_set_ps1(s); 178 this->Data[0].Data = _mm_add_ps(this->Data[0].Data, Operand); 179 this->Data[1].Data = _mm_add_ps(this->Data[1].Data, Operand); 180 this->Data[2].Data = _mm_add_ps(this->Data[2].Data, Operand); 181 this->Data[3].Data = _mm_add_ps(this->Data[3].Data, Operand); 182 return *this; 183 } 184 185 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator-= 186 ( 187 float const & s 188 ) 189 { 190 __m128 Operand = _mm_set_ps1(s); 191 this->Data[0].Data = _mm_sub_ps(this->Data[0].Data, Operand); 192 this->Data[1].Data = _mm_sub_ps(this->Data[1].Data, Operand); 193 this->Data[2].Data = _mm_sub_ps(this->Data[2].Data, Operand); 194 this->Data[3].Data = _mm_sub_ps(this->Data[3].Data, Operand); 195 return *this; 196 } 197 198 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator*= 199 ( 200 float const & s 201 ) 202 { 203 __m128 Operand = _mm_set_ps1(s); 204 this->Data[0].Data = _mm_mul_ps(this->Data[0].Data, Operand); 205 this->Data[1].Data = _mm_mul_ps(this->Data[1].Data, Operand); 206 this->Data[2].Data = _mm_mul_ps(this->Data[2].Data, Operand); 207 this->Data[3].Data = _mm_mul_ps(this->Data[3].Data, Operand); 208 return *this; 209 } 210 211 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator/= 212 ( 213 float const & s 214 ) 215 { 216 __m128 Operand = _mm_div_ps(one, _mm_set_ps1(s)); 217 this->Data[0].Data = _mm_mul_ps(this->Data[0].Data, Operand); 218 this->Data[1].Data = _mm_mul_ps(this->Data[1].Data, Operand); 219 this->Data[2].Data = _mm_mul_ps(this->Data[2].Data, Operand); 220 this->Data[3].Data = _mm_mul_ps(this->Data[3].Data, Operand); 221 return *this; 222 } 223 224 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator++ () 225 { 226 this->Data[0].Data = _mm_add_ps(this->Data[0].Data, one); 227 this->Data[1].Data = _mm_add_ps(this->Data[1].Data, one); 228 this->Data[2].Data = _mm_add_ps(this->Data[2].Data, one); 229 this->Data[3].Data = _mm_add_ps(this->Data[3].Data, one); 230 return *this; 231 } 232 233 GLM_FUNC_QUALIFIER fmat4x4SIMD & fmat4x4SIMD::operator-- () 234 { 235 this->Data[0].Data = _mm_sub_ps(this->Data[0].Data, one); 236 this->Data[1].Data = _mm_sub_ps(this->Data[1].Data, one); 237 this->Data[2].Data = _mm_sub_ps(this->Data[2].Data, one); 238 this->Data[3].Data = _mm_sub_ps(this->Data[3].Data, one); 239 return *this; 240 } 241 242 243 ////////////////////////////////////////////////////////////// 244 // Binary operators 245 246 GLM_FUNC_QUALIFIER fmat4x4SIMD operator+ 247 ( 248 const fmat4x4SIMD &m, 249 float const & s 250 ) 251 { 252 return detail::fmat4x4SIMD 253 ( 254 m[0] + s, 255 m[1] + s, 256 m[2] + s, 257 m[3] + s 258 ); 259 } 260 261 GLM_FUNC_QUALIFIER fmat4x4SIMD operator+ 262 ( 263 float const & s, 264 const fmat4x4SIMD &m 265 ) 266 { 267 return detail::fmat4x4SIMD 268 ( 269 m[0] + s, 270 m[1] + s, 271 m[2] + s, 272 m[3] + s 273 ); 274 } 275 276 GLM_FUNC_QUALIFIER fmat4x4SIMD operator+ 277 ( 278 const fmat4x4SIMD &m1, 279 const fmat4x4SIMD &m2 280 ) 281 { 282 return detail::fmat4x4SIMD 283 ( 284 m1[0] + m2[0], 285 m1[1] + m2[1], 286 m1[2] + m2[2], 287 m1[3] + m2[3] 288 ); 289 } 290 291 292 GLM_FUNC_QUALIFIER fmat4x4SIMD operator- 293 ( 294 const fmat4x4SIMD &m, 295 float const & s 296 ) 297 { 298 return detail::fmat4x4SIMD 299 ( 300 m[0] - s, 301 m[1] - s, 302 m[2] - s, 303 m[3] - s 304 ); 305 } 306 307 GLM_FUNC_QUALIFIER fmat4x4SIMD operator- 308 ( 309 float const & s, 310 const fmat4x4SIMD &m 311 ) 312 { 313 return detail::fmat4x4SIMD 314 ( 315 s - m[0], 316 s - m[1], 317 s - m[2], 318 s - m[3] 319 ); 320 } 321 322 GLM_FUNC_QUALIFIER fmat4x4SIMD operator- 323 ( 324 const fmat4x4SIMD &m1, 325 const fmat4x4SIMD &m2 326 ) 327 { 328 return detail::fmat4x4SIMD 329 ( 330 m1[0] - m2[0], 331 m1[1] - m2[1], 332 m1[2] - m2[2], 333 m1[3] - m2[3] 334 ); 335 } 336 337 338 GLM_FUNC_QUALIFIER fmat4x4SIMD operator* 339 ( 340 const fmat4x4SIMD &m, 341 float const & s 342 ) 343 { 344 return detail::fmat4x4SIMD 345 ( 346 m[0] * s, 347 m[1] * s, 348 m[2] * s, 349 m[3] * s 350 ); 351 } 352 353 GLM_FUNC_QUALIFIER fmat4x4SIMD operator* 354 ( 355 float const & s, 356 const fmat4x4SIMD &m 357 ) 358 { 359 return detail::fmat4x4SIMD 360 ( 361 m[0] * s, 362 m[1] * s, 363 m[2] * s, 364 m[3] * s 365 ); 366 } 367 368 GLM_FUNC_QUALIFIER fvec4SIMD operator* 369 ( 370 const fmat4x4SIMD &m, 371 fvec4SIMD const & v 372 ) 373 { 374 return sse_mul_ps(&m.Data[0].Data, v.Data); 375 } 376 377 GLM_FUNC_QUALIFIER fvec4SIMD operator* 378 ( 379 fvec4SIMD const & v, 380 const fmat4x4SIMD &m 381 ) 382 { 383 return sse_mul_ps(v.Data, &m.Data[0].Data); 384 } 385 386 GLM_FUNC_QUALIFIER fmat4x4SIMD operator* 387 ( 388 const fmat4x4SIMD &m1, 389 const fmat4x4SIMD &m2 390 ) 391 { 392 fmat4x4SIMD result; 393 sse_mul_ps(&m1.Data[0].Data, &m2.Data[0].Data, &result.Data[0].Data); 394 395 return result; 396 } 397 398 399 400 GLM_FUNC_QUALIFIER fmat4x4SIMD operator/ 401 ( 402 const fmat4x4SIMD &m, 403 float const & s 404 ) 405 { 406 return detail::fmat4x4SIMD 407 ( 408 m[0] / s, 409 m[1] / s, 410 m[2] / s, 411 m[3] / s 412 ); 413 } 414 415 GLM_FUNC_QUALIFIER fmat4x4SIMD operator/ 416 ( 417 float const & s, 418 const fmat4x4SIMD &m 419 ) 420 { 421 return detail::fmat4x4SIMD 422 ( 423 s / m[0], 424 s / m[1], 425 s / m[2], 426 s / m[3] 427 ); 428 } 429 430 GLM_FUNC_QUALIFIER detail::fmat4x4SIMD inverse(detail::fmat4x4SIMD const & m) 431 { 432 detail::fmat4x4SIMD result; 433 detail::sse_inverse_ps(&m[0].Data, &result[0].Data); 434 return result; 435 } 436 437 GLM_FUNC_QUALIFIER fvec4SIMD operator/ 438 ( 439 const fmat4x4SIMD & m, 440 fvec4SIMD const & v 441 ) 442 { 443 return inverse(m) * v; 444 } 445 446 GLM_FUNC_QUALIFIER fvec4SIMD operator/ 447 ( 448 fvec4SIMD const & v, 449 const fmat4x4SIMD &m 450 ) 451 { 452 return v * inverse(m); 453 } 454 455 GLM_FUNC_QUALIFIER fmat4x4SIMD operator/ 456 ( 457 const fmat4x4SIMD &m1, 458 const fmat4x4SIMD &m2 459 ) 460 { 461 __m128 result[4]; 462 __m128 inv[4]; 463 464 sse_inverse_ps(&m2.Data[0].Data, inv); 465 sse_mul_ps(&m1.Data[0].Data, inv, result); 466 467 return fmat4x4SIMD(result); 468 } 469 470 471 ////////////////////////////////////////////////////////////// 472 // Unary constant operators 473 GLM_FUNC_QUALIFIER fmat4x4SIMD const operator- 474 ( 475 fmat4x4SIMD const & m 476 ) 477 { 478 return detail::fmat4x4SIMD 479 ( 480 -m[0], 481 -m[1], 482 -m[2], 483 -m[3] 484 ); 485 } 486 487 GLM_FUNC_QUALIFIER fmat4x4SIMD const operator-- 488 ( 489 fmat4x4SIMD const & m, 490 int 491 ) 492 { 493 return detail::fmat4x4SIMD 494 ( 495 m[0] - 1.0f, 496 m[1] - 1.0f, 497 m[2] - 1.0f, 498 m[3] - 1.0f 499 ); 500 } 501 502 GLM_FUNC_QUALIFIER fmat4x4SIMD const operator++ 503 ( 504 fmat4x4SIMD const & m, 505 int 506 ) 507 { 508 return detail::fmat4x4SIMD 509 ( 510 m[0] + 1.0f, 511 m[1] + 1.0f, 512 m[2] + 1.0f, 513 m[3] + 1.0f 514 ); 515 } 516 517 }//namespace detail 518 519 GLM_FUNC_QUALIFIER mat4 mat4_cast 520 ( 521 detail::fmat4x4SIMD const & x 522 ) 523 { 524 GLM_ALIGN(16) mat4 Result; 525 _mm_store_ps(&Result[0][0], x.Data[0].Data); 526 _mm_store_ps(&Result[1][0], x.Data[1].Data); 527 _mm_store_ps(&Result[2][0], x.Data[2].Data); 528 _mm_store_ps(&Result[3][0], x.Data[3].Data); 529 return Result; 530 } 531 532 GLM_FUNC_QUALIFIER detail::fmat4x4SIMD matrixCompMult 533 ( 534 detail::fmat4x4SIMD const & x, 535 detail::fmat4x4SIMD const & y 536 ) 537 { 538 detail::fmat4x4SIMD result; 539 result[0] = x[0] * y[0]; 540 result[1] = x[1] * y[1]; 541 result[2] = x[2] * y[2]; 542 result[3] = x[3] * y[3]; 543 return result; 544 } 545 546 GLM_FUNC_QUALIFIER detail::fmat4x4SIMD outerProduct 547 ( 548 detail::fvec4SIMD const & c, 549 detail::fvec4SIMD const & r 550 ) 551 { 552 __m128 Shu0 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(0, 0, 0, 0)); 553 __m128 Shu1 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(1, 1, 1, 1)); 554 __m128 Shu2 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(2, 2, 2, 2)); 555 __m128 Shu3 = _mm_shuffle_ps(r.Data, r.Data, _MM_SHUFFLE(3, 3, 3, 3)); 556 557 detail::fmat4x4SIMD result(detail::fmat4x4SIMD::_null); 558 result[0].Data = _mm_mul_ps(c.Data, Shu0); 559 result[1].Data = _mm_mul_ps(c.Data, Shu1); 560 result[2].Data = _mm_mul_ps(c.Data, Shu2); 561 result[3].Data = _mm_mul_ps(c.Data, Shu3); 562 return result; 563 } 564 565 GLM_FUNC_QUALIFIER detail::fmat4x4SIMD transpose(detail::fmat4x4SIMD const & m) 566 { 567 detail::fmat4x4SIMD result; 568 detail::sse_transpose_ps(&m[0].Data, &result[0].Data); 569 return result; 570 } 571 572 GLM_FUNC_QUALIFIER float determinant(detail::fmat4x4SIMD const & m) 573 { 574 float Result; 575 _mm_store_ss(&Result, detail::sse_det_ps(&m[0].Data)); 576 return Result; 577 } 578 579 }//namespace glm 580