linear_algebra.h (19125B)
1 #pragma once 2 3 /* 4 * vector/matrix code 5 */ 6 7 #include <math.h> 8 9 #include "intrinsics.h" 10 #include "platform_alignment.h" 11 #include "platform_inline.h" 12 13 struct m4; 14 15 /* 16 * data definitions 17 */ 18 19 // AUTOVISITOR 20 struct v2 { 21 float x, y; 22 23 v2() { } 24 25 explicit v2( float a ) { 26 x = a; 27 y = a; 28 } 29 30 explicit v2( float a, float b ) { 31 x = a; 32 y = b; 33 } 34 35 v2 xx() const { return v2( x, x ); } 36 v2 xy() const { return v2( x, y ); } 37 v2 yx() const { return v2( y, x ); } 38 v2 yy() const { return v2( y, y ); } 39 }; 40 41 // AUTOVISITOR 42 struct v2u32 { 43 u32 x, y; 44 45 v2u32() { } 46 47 explicit v2u32( u32 a, u32 b ) { 48 x = a; 49 y = b; 50 } 51 }; 52 53 // AUTOVISITOR 54 struct v2s32 { 55 s32 x, y; 56 57 v2s32() { } 58 59 explicit v2s32( s32 a, s32 b ) { 60 x = a; 61 y = b; 62 } 63 }; 64 65 // AUTOVISITOR 66 struct v3 { 67 float x, y, z; 68 69 v3() { } 70 71 explicit v3( float a ) { 72 x = a; 73 y = a; 74 z = a; 75 } 76 77 explicit v3( float a, float b, float c ) { 78 x = a; 79 y = b; 80 z = c; 81 } 82 83 explicit v3( v2 v, float c ) { 84 x = v.x; 85 y = v.y; 86 z = c; 87 } 88 89 explicit v3( float a, v2 v ) { 90 x = a; 91 y = v.x; 92 z = v.y; 93 } 94 95 float & operator[]( size_t idx ) { 96 ASSERT( idx < 3 ); 97 if( idx == 0 ) return x; 98 if( idx == 1 ) return y; 99 return z; 100 } 101 102 const float & operator[]( size_t idx ) const { 103 ASSERT( idx < 3 ); 104 if( idx == 0 ) return x; 105 if( idx == 1 ) return y; 106 return z; 107 } 108 109 v2 xy() const { return v2( x, y ); } 110 111 float * ptr() { return &x; } 112 }; 113 114 // AUTOVISITOR 115 struct v3u32 { 116 u32 x, y, z; 117 118 v3u32() { } 119 120 explicit v3u32( u32 a, u32 b, u32 c ) { 121 x = a; 122 y = b; 123 z = c; 124 } 125 }; 126 127 // AUTOVISITOR 128 struct m3 { 129 v3 col0, col1, col2; 130 131 m3() { } 132 133 explicit m3( 134 float e00, float e01, float e02, 135 float e10, float e11, float e12, 136 float e20, float e21, float e22 137 ) { 138 col0 = v3( e00, e10, e20 ); 139 col1 = v3( e01, e11, e21 ); 140 col2 = v3( e02, e12, e22 ); 141 } 142 143 explicit m3( const v3 & c0, const v3 & c1, const v3 & c2 ) { 144 col0 = c0; 145 col1 = c1; 146 col2 = c2; 147 } 148 149 explicit m3( const m4 & m ); 150 151 v3 row0() const { return v3( col0.x, col1.x, col2.x ); } 152 v3 row1() const { return v3( col0.y, col1.y, col2.y ); } 153 v3 row2() const { return v3( col0.z, col1.z, col2.z ); } 154 }; 155 156 struct Ray3 { 157 v3 origin; 158 v3 dir; 159 v3 inv_dir; 160 161 explicit Ray3( v3 o, v3 d ) { 162 origin = o; 163 dir = d; 164 inv_dir = v3( 1.0f / d.x, 1.0f / d.y, 1.0f / d.z ); 165 } 166 }; 167 168 // AUTOVISITOR 169 struct ALIGNTO_SSE v4 { 170 float x, y, z, w; 171 172 v4() { } 173 174 explicit v4( float a ) { 175 x = a; 176 y = a; 177 z = a; 178 w = a; 179 } 180 181 explicit v4( float a, float b, float c, float d ) { 182 x = a; 183 y = b; 184 z = c; 185 w = d; 186 } 187 188 explicit v4( v3 abc, float d ) { 189 x = abc.x; 190 y = abc.y; 191 z = abc.z; 192 w = d; 193 } 194 195 float & operator[]( size_t idx ) { 196 ASSERT( idx < 4 ); 197 if( idx == 0 ) return x; 198 if( idx == 1 ) return y; 199 if( idx == 2 ) return z; 200 return w; 201 } 202 203 const float & operator[]( size_t idx ) const { 204 ASSERT( idx < 4 ); 205 if( idx == 0 ) return x; 206 if( idx == 1 ) return y; 207 if( idx == 2 ) return z; 208 return w; 209 } 210 211 v2 xy() const { return v2( x, y ); } 212 v3 xyz() const { return v3( x, y, z ); } 213 214 float * ptr() { return &x; } 215 }; 216 217 // AUTOVISITOR 218 struct ALIGNTO_SSE m4 { 219 v4 col0, col1, col2, col3; 220 221 m4() { } 222 223 explicit m4( 224 float e00, float e01, float e02, float e03, 225 float e10, float e11, float e12, float e13, 226 float e20, float e21, float e22, float e23, 227 float e30, float e31, float e32, float e33 228 ) { 229 col0 = v4( e00, e10, e20, e30 ); 230 col1 = v4( e01, e11, e21, e31 ); 231 col2 = v4( e02, e12, e22, e32 ); 232 col3 = v4( e03, e13, e23, e33 ); 233 } 234 235 explicit m4( const v4 & c0, const v4 & c1, const v4 & c2, const v4 & c3 ) { 236 col0 = c0; 237 col1 = c1; 238 col2 = c2; 239 col3 = c3; 240 } 241 242 v4 row0() const { return v4( col0.x, col1.x, col2.x, col3.x ); } 243 v4 row1() const { return v4( col0.y, col1.y, col2.y, col3.y ); } 244 v4 row2() const { return v4( col0.z, col1.z, col2.z, col3.z ); } 245 v4 row3() const { return v4( col0.w, col1.w, col2.w, col3.w ); } 246 247 float * ptr() { return col0.ptr(); } 248 }; 249 250 forceinline m3::m3( const m4 & m ) { 251 col0 = m.col0.xyz(); 252 col1 = m.col1.xyz(); 253 col2 = m.col2.xyz(); 254 } 255 256 // AUTOVISITOR 257 struct quat { 258 float x, y, z, w; 259 260 quat() { } 261 262 explicit quat( float a, float b, float c, float d ) { 263 x = a; 264 y = b; 265 z = c; 266 w = d; 267 } 268 269 float * ptr() { return &x; } 270 }; 271 272 // TODO: v3x4, v4x4, simd matrices? 273 274 /* 275 * misc. TODO: put this stuff somewhere else 276 */ 277 278 forceinline float deg_to_rad( float x ) { 279 return x * PI / 180.0f; 280 } 281 282 forceinline float rad_to_deg( float x ) { 283 return x * 180.0f / PI; 284 } 285 286 forceinline v3 deg_to_rad( const v3 & v ) { 287 return v3( deg_to_rad( v.x ), deg_to_rad( v.y ), deg_to_rad( v.z ) ); 288 } 289 290 forceinline v3 rad_to_deg( const v3 & v ) { 291 return v3( rad_to_deg( v.x ), rad_to_deg( v.y ), rad_to_deg( v.z ) ); 292 } 293 294 /* 295 * v2 296 */ 297 298 forceinline v2 operator+( v2 v, float x ) { 299 return v2( v.x + x, v.y + x ); 300 } 301 302 forceinline v2 operator+( v2 lhs, v2 rhs ) { 303 return v2( lhs.x + rhs.x, lhs.y + rhs.y ); 304 } 305 306 forceinline v2 operator-( v2 v, float x ) { 307 return v2( v.x - x, v.y - x ); 308 } 309 310 forceinline v2 operator-( v2 lhs, v2 rhs ) { 311 return v2( lhs.x - rhs.x, lhs.y - rhs.y ); 312 } 313 314 forceinline v2 operator*( v2 v, float scale ) { 315 return v2( v.x * scale, v.y * scale ); 316 } 317 318 forceinline void operator*=( v2 & v, float scale ) { 319 v = v * scale; 320 } 321 322 forceinline v2 operator*( float scale, v2 v ) { 323 return v * scale; 324 } 325 326 forceinline v2 operator*( v2 lhs, v2 rhs ) { 327 return v2( lhs.x * rhs.x, lhs.y * rhs.y ); 328 } 329 330 forceinline void operator*=( v2 & lhs, v2 rhs ) { 331 lhs = lhs * rhs; 332 } 333 334 forceinline v2 operator/( v2 v, float scale ) { 335 float inv_scale = 1.0f / scale; 336 return v * inv_scale; 337 } 338 339 forceinline v2 operator-( v2 v ) { 340 return v2( -v.x, -v.y ); 341 } 342 343 forceinline float dot( v2 lhs, v2 rhs ) { 344 return lhs.x * rhs.x + lhs.y * rhs.y; 345 } 346 347 forceinline float length( v2 v ) { 348 return sqrtf( v.x * v.x + v.y * v.y ); 349 } 350 351 forceinline v2 normalize( v2 v ) { 352 return v / length( v ); 353 } 354 355 forceinline v2 floorf( v2 v ) { 356 return v2( floorf( v.x ), floorf( v.y ) ); 357 } 358 359 /* 360 * v2s32 361 */ 362 363 forceinline v2s32 operator+( v2s32 lhs, v2s32 rhs ) { 364 return v2s32( lhs.x + rhs.x, lhs.y + rhs.y ); 365 } 366 367 forceinline v2s32 operator-( v2s32 lhs, v2s32 rhs ) { 368 return v2s32( lhs.x - rhs.x, lhs.y - rhs.y ); 369 } 370 371 forceinline v2s32 operator/( v2s32 v, u32 d ) { 372 return v2s32( v.x / d, v.y / d ); 373 } 374 375 forceinline s32 dot( v2s32 lhs, v2s32 rhs ) { 376 return lhs.x * rhs.x + lhs.y * rhs.y; 377 } 378 379 /* 380 * v3 381 */ 382 383 forceinline v3 rcp( v3 v ) { 384 return v3( 1.0f / v.x, 1.0f / v.y, 1.0f / v.z ); 385 } 386 387 forceinline v3 operator+( v3 lhs, v3 rhs ) { 388 return v3( lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z ); 389 } 390 391 forceinline void operator+=( v3 & lhs, v3 rhs ) { 392 lhs = lhs + rhs; 393 } 394 395 forceinline v3 operator-( v3 lhs, v3 rhs ) { 396 return v3( lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z ); 397 } 398 399 forceinline void operator-=( v3 & lhs, v3 rhs ) { 400 lhs = lhs - rhs; 401 } 402 403 forceinline v3 operator*( v3 v, float scale ) { 404 return v3( v.x * scale, v.y * scale, v.z * scale ); 405 } 406 407 forceinline v3 operator*( float scale, v3 v ) { 408 return v * scale; 409 } 410 411 forceinline void operator*=( v3 & v, float scale ) { 412 v = v * scale; 413 } 414 415 forceinline v3 operator*( v3 lhs, v3 rhs ) { 416 return v3( lhs.x * rhs.x, lhs.y * rhs.y, lhs.z * rhs.z ); 417 } 418 419 forceinline v3 operator/( v3 v, float scale ) { 420 float inv_scale = 1.0f / scale; 421 return v * inv_scale; 422 } 423 424 forceinline void operator/=( v3 & v, float scale ) { 425 v = v / scale; 426 } 427 428 forceinline v3 operator/( v3 lhs, v3 rhs ) { 429 return lhs * rcp( rhs ); 430 } 431 432 forceinline v3 operator-( v3 v ) { 433 return v3( -v.x, -v.y, -v.z ); 434 } 435 436 forceinline bool operator==( v3 lhs, v3 rhs ) { 437 return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; 438 } 439 440 forceinline float dot( v3 lhs, v3 rhs ) { 441 return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; 442 } 443 444 forceinline v3 cross( v3 lhs, v3 rhs ) { 445 return v3( 446 lhs.y * rhs.z - rhs.y * lhs.z, 447 rhs.x * lhs.z - lhs.x * rhs.z, 448 lhs.x * rhs.y - rhs.x * lhs.y 449 ); 450 } 451 452 forceinline float length( v3 v ) { 453 return sqrtf( v.x * v.x + v.y * v.y + v.z * v.z ); 454 } 455 456 forceinline v3 normalize( v3 v ) { 457 return v / length( v ); 458 } 459 460 forceinline v3 expf( v3 v ) { 461 return v3( expf( v.x ), expf( v.y ), expf( v.z ) ); 462 } 463 464 forceinline v3 powf( v3 v, v3 e ) { 465 return v3( powf( v.x, e.x ), powf( v.y, e.y ), powf( v.z, e.z ) ); 466 } 467 468 forceinline v3 v3_forward( float pitch, float yaw ) { 469 pitch = deg_to_rad( pitch ); 470 yaw = deg_to_rad( yaw ); 471 return v3( 472 cosf( pitch ) * cosf( yaw ), 473 cosf( pitch ) * sinf( yaw ), 474 sinf( pitch ) 475 ); 476 } 477 478 forceinline v3 v3_forward_xy( float yaw ) { 479 yaw = deg_to_rad( yaw ); 480 return v3( cosf( yaw ), sinf( yaw ), 0 ); 481 } 482 483 /* 484 * v3u32 485 */ 486 487 forceinline v3u32 operator+( v3u32 lhs, v3u32 rhs ) { 488 return v3u32( lhs.x + rhs.x, lhs.y + rhs.y, lhs.z + rhs.z ); 489 } 490 491 forceinline v3u32 operator-( v3u32 lhs, v3u32 rhs ) { 492 return v3u32( lhs.x - rhs.x, lhs.y - rhs.y, lhs.z - rhs.z ); 493 } 494 495 forceinline v3u32 operator/( v3u32 v, u32 d ) { 496 return v3u32( v.x / d, v.y / d, v.z / d ); 497 } 498 499 forceinline u32 dot( v3u32 lhs, v3u32 rhs ) { 500 return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z; 501 } 502 503 /* 504 * m3 505 */ 506 507 forceinline m3 m3_identity() { 508 return m3( 509 1, 0, 0, 510 0, 1, 0, 511 0, 0, 1 512 ); 513 } 514 515 forceinline m3 m3_scale( float s ) { 516 return m3( 517 s, 0, 0, 518 0, s, 0, 519 0, 0, s 520 ); 521 } 522 523 forceinline m3 m3_scale( float x, float y, float z ) { 524 return m3( 525 x, 0, 0, 526 0, y, 0, 527 0, 0, z 528 ); 529 } 530 531 forceinline m3 m3_rotx( float theta ) { 532 float s = sinf( theta ); 533 float c = cosf( theta ); 534 return m3( 535 1, 0, 0, 536 0, c, -s, 537 0, s, c 538 ); 539 } 540 541 forceinline m3 m3_roty( float theta ) { 542 float s = sinf( theta ); 543 float c = cosf( theta ); 544 return m3( 545 c, 0, s, 546 0, 1, 0, 547 -s, 0, c 548 ); 549 } 550 551 forceinline m3 m3_rotz( float theta ) { 552 float s = sinf( theta ); 553 float c = cosf( theta ); 554 return m3( 555 c, -s, 0, 556 s, c, 0, 557 0, 0, 1 558 ); 559 } 560 561 forceinline m3 operator*( const m3 & lhs, const m3 & rhs ) { 562 return m3( 563 dot( lhs.row0(), rhs.col0 ), 564 dot( lhs.row0(), rhs.col1 ), 565 dot( lhs.row0(), rhs.col2 ), 566 567 dot( lhs.row1(), rhs.col0 ), 568 dot( lhs.row1(), rhs.col1 ), 569 dot( lhs.row1(), rhs.col2 ), 570 571 dot( lhs.row2(), rhs.col0 ), 572 dot( lhs.row2(), rhs.col1 ), 573 dot( lhs.row2(), rhs.col2 ) 574 ); 575 } 576 577 forceinline v3 operator*( const m3 & m, v3 v ) { 578 return v3( 579 dot( m.row0(), v ), 580 dot( m.row1(), v ), 581 dot( m.row2(), v ) 582 ); 583 } 584 585 forceinline m3 operator-( const m3 & m ) { 586 return m3( -m.col0, -m.col1, -m.col2 ); 587 } 588 589 /* 590 * v4 591 */ 592 593 forceinline v4 operator+( v4 lhs, v4 rhs ) { 594 return v4( 595 lhs.x + rhs.x, 596 lhs.y + rhs.y, 597 lhs.z + rhs.z, 598 lhs.w + rhs.w 599 ); 600 } 601 602 forceinline v4 operator-( v4 lhs, v4 rhs ) { 603 return v4( 604 lhs.x - rhs.x, 605 lhs.y - rhs.y, 606 lhs.z - rhs.z, 607 lhs.w - rhs.w 608 ); 609 } 610 611 forceinline v4 operator*( v4 v, float scale ) { 612 return v4( 613 v.x * scale, 614 v.y * scale, 615 v.z * scale, 616 v.w * scale 617 ); 618 } 619 620 forceinline v4 operator*( float scale, v4 v ) { 621 return v * scale; 622 } 623 624 forceinline v4 operator/( v4 v, float scale ) { 625 float inv_scale = 1.0f / scale; 626 return v * inv_scale; 627 } 628 629 forceinline void operator/=( v4 & v, float scale ) { 630 v = v / scale; 631 } 632 633 forceinline v4 operator-( v4 v ) { 634 return v4( -v.x, -v.y, -v.z, -v.w ); 635 } 636 637 forceinline float dot( v4 lhs, v4 rhs ) { 638 return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w; 639 } 640 641 forceinline float length( v4 v ) { 642 return sqrtf( v.x * v.x + v.y * v.y + v.z * v.z + v.w * v.w ); 643 } 644 645 forceinline v4 normalize( v4 v ) { 646 return v / length( v ); 647 } 648 649 /* 650 * m4 651 */ 652 653 forceinline m4 m4_identity() { 654 return m4( 655 1, 0, 0, 0, 656 0, 1, 0, 0, 657 0, 0, 1, 0, 658 0, 0, 0, 1 659 ); 660 } 661 662 forceinline m4 m4_scale( float s ) { 663 return m4( 664 s, 0, 0, 0, 665 0, s, 0, 0, 666 0, 0, s, 0, 667 0, 0, 0, 1 668 ); 669 } 670 671 forceinline m4 m4_scale( float x, float y, float z ) { 672 return m4( 673 x, 0, 0, 0, 674 0, y, 0, 0, 675 0, 0, z, 0, 676 0, 0, 0, 1 677 ); 678 } 679 680 forceinline m4 m4_rotx( float theta ) { 681 float s = sinf( theta ); 682 float c = cosf( theta ); 683 return m4( 684 1, 0, 0, 0, 685 0, c, -s, 0, 686 0, s, c, 0, 687 0, 0, 0, 1 688 ); 689 } 690 691 forceinline m4 m4_roty( float theta ) { 692 float s = sinf( theta ); 693 float c = cosf( theta ); 694 return m4( 695 c, 0, s, 0, 696 0, 1, 0, 0, 697 -s, 0, c, 0, 698 0, 0, 0, 1 699 ); 700 } 701 702 forceinline m4 m4_rotz( float theta ) { 703 float s = sinf( theta ); 704 float c = cosf( theta ); 705 return m4( 706 c, -s, 0, 0, 707 s, c, 0, 0, 708 0, 0, 1, 0, 709 0, 0, 0, 1 710 ); 711 } 712 713 forceinline m4 m4_rotz90() { 714 return m4( 715 0, -1, 0, 0, 716 1, 0, 0, 0, 717 0, 0, 1, 0, 718 0, 0, 0, 1 719 ); 720 } 721 722 forceinline m4 m4_rotz180() { 723 return m4( 724 -1, 0, 0, 0, 725 0, -1, 0, 0, 726 0, 0, 1, 0, 727 0, 0, 0, 1 728 ); 729 } 730 731 forceinline m4 m4_rotz270() { 732 return m4( 733 0, 1, 0, 0, 734 -1, 0, 0, 0, 735 0, 0, 1, 0, 736 0, 0, 0, 1 737 ); 738 } 739 740 forceinline m4 m4_translation( float x, float y, float z ) { 741 return m4( 742 1, 0, 0, x, 743 0, 1, 0, y, 744 0, 0, 1, z, 745 0, 0, 0, 1 746 ); 747 } 748 749 forceinline m4 m4_translation( v3 xyz ) { 750 return m4_translation( xyz.x, xyz.y, xyz.z ); 751 } 752 753 forceinline m4 m4_ortho( float left, float right, float top, float bottom, float near_plane, float far_plane ) { 754 return m4( 755 2.0f / ( right - left ), 756 0.0f, 757 0.0f, 758 -( right + left ) / ( right - left ), 759 760 0.0f, 761 2.0f / ( top - bottom ), 762 0.0f, 763 -( top + bottom ) / ( top - bottom ), 764 765 0.0f, 766 0.0f, 767 -2.0f / ( far_plane - near_plane ), 768 -( far_plane + near_plane ) / ( far_plane - near_plane ), 769 770 0.0f, 771 0.0f, 772 0.0f, 773 1.0f 774 ); 775 } 776 777 forceinline m4 m4_perspective( float vertical_fov_degrees, float aspect_ratio, float near_plane, float far_plane ) { 778 float tan_half_vertical_fov = tanf( deg_to_rad( vertical_fov_degrees ) / 2.0f ); 779 780 return m4( 781 1.0f / ( tan_half_vertical_fov * aspect_ratio ), 782 0.0f, 783 0.0f, 784 0.0f, 785 786 0.0f, 787 1.0f / tan_half_vertical_fov, 788 0.0f, 789 0.0f, 790 791 0.0f, 792 0.0f, 793 -( far_plane + near_plane ) / ( far_plane - near_plane ), 794 -( 2.0f * far_plane * near_plane ) / ( far_plane - near_plane ), 795 796 0.0f, 797 0.0f, 798 -1.0f, 799 0.0f 800 ); 801 } 802 803 forceinline m4 m4_perspective_inf( float vertical_fov_degrees, float aspect_ratio, float near_plane ) { 804 float tan_half_vertical_fov = tanf( deg_to_rad( vertical_fov_degrees ) / 2.0f ); 805 float epsilon = 2.4e-6f; 806 807 return m4( 808 1.0f / ( tan_half_vertical_fov * aspect_ratio ), 809 0.0f, 810 0.0f, 811 0.0f, 812 813 0.0f, 814 1.0f / tan_half_vertical_fov, 815 0.0f, 816 0.0f, 817 818 0.0f, 819 0.0f, 820 epsilon - 1.0f, 821 ( epsilon - 2.0f ) * near_plane, 822 823 0.0f, 824 0.0f, 825 -1.0f, 826 0.0f 827 ); 828 } 829 830 forceinline m4 operator*( const m4 & lhs, const m4 & rhs ) { 831 return m4( 832 dot( lhs.row0(), rhs.col0 ), 833 dot( lhs.row0(), rhs.col1 ), 834 dot( lhs.row0(), rhs.col2 ), 835 dot( lhs.row0(), rhs.col3 ), 836 837 dot( lhs.row1(), rhs.col0 ), 838 dot( lhs.row1(), rhs.col1 ), 839 dot( lhs.row1(), rhs.col2 ), 840 dot( lhs.row1(), rhs.col3 ), 841 842 dot( lhs.row2(), rhs.col0 ), 843 dot( lhs.row2(), rhs.col1 ), 844 dot( lhs.row2(), rhs.col2 ), 845 dot( lhs.row2(), rhs.col3 ), 846 847 dot( lhs.row3(), rhs.col0 ), 848 dot( lhs.row3(), rhs.col1 ), 849 dot( lhs.row3(), rhs.col2 ), 850 dot( lhs.row3(), rhs.col3 ) 851 ); 852 } 853 854 forceinline void operator*=( m4 & lhs, const m4 & rhs ) { 855 lhs = lhs * rhs; 856 } 857 858 forceinline v4 operator*( const m4 & m, v4 v ) { 859 return v4( 860 dot( m.row0(), v ), 861 dot( m.row1(), v ), 862 dot( m.row2(), v ), 863 dot( m.row3(), v ) 864 ); 865 } 866 867 forceinline m4 operator-( const m4 & m ) { 868 return m4( -m.col0, -m.col1, -m.col2, -m.col3 ); 869 } 870 871 forceinline m4 m4_view( const v3 & forward, const v3 & right, const v3 & up, const v3 & position ) { 872 m4 rotation( 873 right.x, right.y, right.z, 0, 874 up.x, up.y, up.z, 0, 875 -forward.x, -forward.y, -forward.z, 0, 876 0, 0, 0, 1 877 ); 878 return rotation * m4_translation( -position ); 879 } 880 881 forceinline m4 m4_lookat( const v3 & position, const v3 & target, const v3 & world_up ) { 882 v3 forward = normalize( target - position ); 883 v3 right = normalize( cross( forward, world_up ) ); 884 v3 up = normalize( cross( right, forward ) ); 885 return m4_view( forward, right, up, position ); 886 } 887 888 /* 889 * quat 890 */ 891 892 forceinline quat quat_identity() { 893 return quat( 0, 0, 0, 1 ); 894 } 895 896 forceinline quat operator+( quat lhs, quat rhs ) { 897 return quat( 898 lhs.x + rhs.x, 899 lhs.y + rhs.y, 900 lhs.z + rhs.z, 901 lhs.w + rhs.w 902 ); 903 } 904 905 forceinline quat operator-( quat lhs, quat rhs ) { 906 return quat( 907 lhs.x - rhs.x, 908 lhs.y - rhs.y, 909 lhs.z - rhs.z, 910 lhs.w - rhs.w 911 ); 912 } 913 914 forceinline quat operator*( quat q, float scale ) { 915 return quat( 916 q.x * scale, 917 q.y * scale, 918 q.z * scale, 919 q.w * scale 920 ); 921 } 922 923 forceinline quat operator*( float scale, quat q ) { 924 return q * scale; 925 } 926 927 forceinline quat operator/( quat q, float scale ) { 928 float inv_scale = 1.0f / scale; 929 return q * inv_scale; 930 } 931 932 forceinline void operator/=( quat & q, float scale ) { 933 q = q / scale; 934 } 935 936 forceinline quat operator-( quat q ) { 937 return quat( -q.x, -q.y, -q.z, -q.w ); 938 } 939 940 forceinline float dot( quat lhs, quat rhs ) { 941 return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z + lhs.w * rhs.w; 942 } 943 944 forceinline float length( quat q ) { 945 return sqrtf( q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w ); 946 } 947 948 forceinline quat normalize( quat q ) { 949 return q / length( q ); 950 } 951 952 forceinline quat nlerp( quat from, float t, quat to ) { 953 float lt = 1.0f - t; 954 float rt = dot( from, to ) > 0 ? t : -t; 955 return normalize( from * lt + to * rt ); 956 } 957 958 /* 959 * misc. TODO: put this stuff somewhere else 960 */ 961 962 forceinline u32 mean( u32 a, u32 b ) { 963 return a / 2 + b / 2 + ( a & b & 1 ); 964 } 965 966 forceinline v3u32 mean( v3u32 mins, v3u32 maxs ) { 967 ASSERT( mins.x <= maxs.x ); 968 ASSERT( mins.y <= maxs.y ); 969 ASSERT( mins.z <= maxs.z ); 970 return mins + ( maxs - mins ) / 2; 971 } 972 973 /* 974 * ggformat support 975 */ 976 977 #include "ggformat.h" 978 979 inline void format( FormatBuffer * fb, const v2 & v, const FormatOpts & opts ) { 980 format( fb, "v2(" ); 981 format( fb, v.x, opts ); 982 format( fb, ", " ); 983 format( fb, v.y, opts ); 984 format( fb, ")" ); 985 } 986 987 inline void format( FormatBuffer * fb, const v3 & v, const FormatOpts & opts ) { 988 format( fb, "v3(" ); 989 format( fb, v.x, opts ); 990 format( fb, ", " ); 991 format( fb, v.y, opts ); 992 format( fb, ", " ); 993 format( fb, v.z, opts ); 994 format( fb, ")" ); 995 } 996 997 inline void format( FormatBuffer * fb, const v3u32 & v, const FormatOpts & opts ) { 998 format( fb, "v3u32(" ); 999 format( fb, v.x, opts ); 1000 format( fb, ", " ); 1001 format( fb, v.y, opts ); 1002 format( fb, ", " ); 1003 format( fb, v.z, opts ); 1004 format( fb, ")" ); 1005 } 1006 1007 inline void format( FormatBuffer * fb, const v4 & v, const FormatOpts & opts ) { 1008 format( fb, "v4(" ); 1009 format( fb, v.x, opts ); 1010 format( fb, ", " ); 1011 format( fb, v.y, opts ); 1012 format( fb, ", " ); 1013 format( fb, v.z, opts ); 1014 format( fb, ", " ); 1015 format( fb, v.w, opts ); 1016 format( fb, ")" ); 1017 } 1018 1019 inline void format( FormatBuffer * fb, const m3 & m, const FormatOpts & opts ) { 1020 format( fb, "m3(" ); 1021 format( fb, m.row0(), opts ); 1022 format( fb, ", " ); 1023 format( fb, m.row1(), opts ); 1024 format( fb, ", " ); 1025 format( fb, m.row2(), opts ); 1026 format( fb, ")" ); 1027 } 1028 1029 inline void format( FormatBuffer * fb, const m4 & m, const FormatOpts & opts ) { 1030 format( fb, "m4(" ); 1031 format( fb, m.row0(), opts ); 1032 format( fb, ", " ); 1033 format( fb, m.row1(), opts ); 1034 format( fb, ", " ); 1035 format( fb, m.row2(), opts ); 1036 format( fb, ", " ); 1037 format( fb, m.row3(), opts ); 1038 format( fb, ")" ); 1039 } 1040 1041 inline void format( FormatBuffer * fb, const quat & q, const FormatOpts & opts ) { 1042 format( fb, "quat(" ); 1043 format( fb, q.x, opts ); 1044 format( fb, ", " ); 1045 format( fb, q.y, opts ); 1046 format( fb, ", " ); 1047 format( fb, q.z, opts ); 1048 format( fb, ", " ); 1049 format( fb, q.w, opts ); 1050 format( fb, ")" ); 1051 } 1052 1053 /* 1054 * autogenerated visitor header 1055 */ 1056 1057 #include "visitors/linear_algebra.h"