raymath.h (63013B)
1 /********************************************************************************************** 2 * 3 * raymath v1.5 - Math functions to work with Vector2, Vector3, Matrix and Quaternions 4 * 5 * CONVENTIONS: 6 * - Matrix structure is defined as row-major (memory layout) but parameters naming AND all 7 * math operations performed by the library consider the structure as it was column-major 8 * It is like transposed versions of the matrices are used for all the maths 9 * It benefits some functions making them cache-friendly and also avoids matrix 10 * transpositions sometimes required by OpenGL 11 * Example: In memory order, row0 is [m0 m4 m8 m12] but in semantic math row0 is [m0 m1 m2 m3] 12 * - Functions are always self-contained, no function use another raymath function inside, 13 * required code is directly re-implemented inside 14 * - Functions input parameters are always received by value (2 unavoidable exceptions) 15 * - Functions use always a "result" variable for return 16 * - Functions are always defined inline 17 * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for convenience) 18 * - No compound literals used to make sure libray is compatible with C++ 19 * 20 * CONFIGURATION: 21 * #define RAYMATH_IMPLEMENTATION 22 * Generates the implementation of the library into the included file. 23 * If not defined, the library is in header only mode and can be included in other headers 24 * or source files without problems. But only ONE file should hold the implementation. 25 * 26 * #define RAYMATH_STATIC_INLINE 27 * Define static inline functions code, so #include header suffices for use. 28 * This may use up lots of memory. 29 * 30 * 31 * LICENSE: zlib/libpng 32 * 33 * Copyright (c) 2015-2024 Ramon Santamaria (@raysan5) 34 * 35 * This software is provided "as-is", without any express or implied warranty. In no event 36 * will the authors be held liable for any damages arising from the use of this software. 37 * 38 * Permission is granted to anyone to use this software for any purpose, including commercial 39 * applications, and to alter it and redistribute it freely, subject to the following restrictions: 40 * 41 * 1. The origin of this software must not be misrepresented; you must not claim that you 42 * wrote the original software. If you use this software in a product, an acknowledgment 43 * in the product documentation would be appreciated but is not required. 44 * 45 * 2. Altered source versions must be plainly marked as such, and must not be misrepresented 46 * as being the original software. 47 * 48 * 3. This notice may not be removed or altered from any source distribution. 49 * 50 **********************************************************************************************/ 51 52 #ifndef RAYMATH_H 53 #define RAYMATH_H 54 55 #if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_STATIC_INLINE) 56 #error "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_STATIC_INLINE is contradictory" 57 #endif 58 59 // Function specifiers definition 60 #if defined(RAYMATH_IMPLEMENTATION) 61 #if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) 62 #define RMAPI __declspec(dllexport) extern inline // We are building raylib as a Win32 shared library (.dll) 63 #elif defined(BUILD_LIBTYPE_SHARED) 64 #define RMAPI __attribute__((visibility("default"))) // We are building raylib as a Unix shared library (.so/.dylib) 65 #elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) 66 #define RMAPI __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) 67 #else 68 #define RMAPI extern inline // Provide external definition 69 #endif 70 #elif defined(RAYMATH_STATIC_INLINE) 71 #define RMAPI static inline // Functions may be inlined, no external out-of-line definition 72 #else 73 #if defined(__TINYC__) 74 #define RMAPI static inline // plain inline not supported by tinycc (See issue #435) 75 #else 76 #define RMAPI inline // Functions may be inlined or external definition used 77 #endif 78 #endif 79 80 //---------------------------------------------------------------------------------- 81 // Defines and Macros 82 //---------------------------------------------------------------------------------- 83 #ifndef PI 84 #define PI 3.14159265358979323846f 85 #endif 86 87 #ifndef EPSILON 88 #define EPSILON 0.000001f 89 #endif 90 91 #ifndef DEG2RAD 92 #define DEG2RAD (PI/180.0f) 93 #endif 94 95 #ifndef RAD2DEG 96 #define RAD2DEG (180.0f/PI) 97 #endif 98 99 // Get float vector for Matrix 100 #ifndef MatrixToFloat 101 #define MatrixToFloat(mat) (MatrixToFloatV(mat).v) 102 #endif 103 104 // Get float vector for Vector3 105 #ifndef Vector3ToFloat 106 #define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v) 107 #endif 108 109 //---------------------------------------------------------------------------------- 110 // Types and Structures Definition 111 //---------------------------------------------------------------------------------- 112 #if !defined(RL_VECTOR2_TYPE) 113 // Vector2 type 114 typedef struct Vector2 { 115 float x; 116 float y; 117 } Vector2; 118 #define RL_VECTOR2_TYPE 119 #endif 120 121 #if !defined(RL_VECTOR3_TYPE) 122 // Vector3 type 123 typedef struct Vector3 { 124 float x; 125 float y; 126 float z; 127 } Vector3; 128 #define RL_VECTOR3_TYPE 129 #endif 130 131 #if !defined(RL_VECTOR4_TYPE) 132 // Vector4 type 133 typedef struct Vector4 { 134 float x; 135 float y; 136 float z; 137 float w; 138 } Vector4; 139 #define RL_VECTOR4_TYPE 140 #endif 141 142 #if !defined(RL_QUATERNION_TYPE) 143 // Quaternion type 144 typedef Vector4 Quaternion; 145 #define RL_QUATERNION_TYPE 146 #endif 147 148 #if !defined(RL_MATRIX_TYPE) 149 // Matrix type (OpenGL style 4x4 - right handed, column major) 150 typedef struct Matrix { 151 float m0, m4, m8, m12; // Matrix first row (4 components) 152 float m1, m5, m9, m13; // Matrix second row (4 components) 153 float m2, m6, m10, m14; // Matrix third row (4 components) 154 float m3, m7, m11, m15; // Matrix fourth row (4 components) 155 } Matrix; 156 #define RL_MATRIX_TYPE 157 #endif 158 159 // NOTE: Helper types to be used instead of array return types for *ToFloat functions 160 typedef struct float3 { 161 float v[3]; 162 } float3; 163 164 typedef struct float16 { 165 float v[16]; 166 } float16; 167 168 #include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabsf() 169 170 //---------------------------------------------------------------------------------- 171 // Module Functions Definition - Utils math 172 //---------------------------------------------------------------------------------- 173 174 // Clamp float value 175 RMAPI float Clamp(float value, float min, float max) 176 { 177 float result = (value < min) ? min : value; 178 179 if (result > max) result = max; 180 181 return result; 182 } 183 184 // Calculate linear interpolation between two floats 185 RMAPI float Lerp(float start, float end, float amount) 186 { 187 float result = start + amount*(end - start); 188 189 return result; 190 } 191 192 // Normalize input value within input range 193 RMAPI float Normalize(float value, float start, float end) 194 { 195 float result = (value - start)/(end - start); 196 197 return result; 198 } 199 200 // Remap input value within input range to output range 201 RMAPI float Remap(float value, float inputStart, float inputEnd, float outputStart, float outputEnd) 202 { 203 float result = (value - inputStart)/(inputEnd - inputStart)*(outputEnd - outputStart) + outputStart; 204 205 return result; 206 } 207 208 // Wrap input value from min to max 209 RMAPI float Wrap(float value, float min, float max) 210 { 211 float result = value - (max - min)*floorf((value - min)/(max - min)); 212 213 return result; 214 } 215 216 // Check whether two given floats are almost equal 217 RMAPI int FloatEquals(float x, float y) 218 { 219 #if !defined(EPSILON) 220 #define EPSILON 0.000001f 221 #endif 222 223 int result = (fabsf(x - y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y)))); 224 225 return result; 226 } 227 228 //---------------------------------------------------------------------------------- 229 // Module Functions Definition - Vector2 math 230 //---------------------------------------------------------------------------------- 231 232 // Vector with components value 0.0f 233 RMAPI Vector2 Vector2Zero(void) 234 { 235 Vector2 result = { 0.0f, 0.0f }; 236 237 return result; 238 } 239 240 // Vector with components value 1.0f 241 RMAPI Vector2 Vector2One(void) 242 { 243 Vector2 result = { 1.0f, 1.0f }; 244 245 return result; 246 } 247 248 // Add two vectors (v1 + v2) 249 RMAPI Vector2 Vector2Add(Vector2 v1, Vector2 v2) 250 { 251 Vector2 result = { v1.x + v2.x, v1.y + v2.y }; 252 253 return result; 254 } 255 256 // Add vector and float value 257 RMAPI Vector2 Vector2AddValue(Vector2 v, float add) 258 { 259 Vector2 result = { v.x + add, v.y + add }; 260 261 return result; 262 } 263 264 // Subtract two vectors (v1 - v2) 265 RMAPI Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) 266 { 267 Vector2 result = { v1.x - v2.x, v1.y - v2.y }; 268 269 return result; 270 } 271 272 // Subtract vector by float value 273 RMAPI Vector2 Vector2SubtractValue(Vector2 v, float sub) 274 { 275 Vector2 result = { v.x - sub, v.y - sub }; 276 277 return result; 278 } 279 280 // Calculate vector length 281 RMAPI float Vector2Length(Vector2 v) 282 { 283 float result = sqrtf((v.x*v.x) + (v.y*v.y)); 284 285 return result; 286 } 287 288 // Calculate vector square length 289 RMAPI float Vector2LengthSqr(Vector2 v) 290 { 291 float result = (v.x*v.x) + (v.y*v.y); 292 293 return result; 294 } 295 296 // Calculate two vectors dot product 297 RMAPI float Vector2DotProduct(Vector2 v1, Vector2 v2) 298 { 299 float result = (v1.x*v2.x + v1.y*v2.y); 300 301 return result; 302 } 303 304 // Calculate distance between two vectors 305 RMAPI float Vector2Distance(Vector2 v1, Vector2 v2) 306 { 307 float result = sqrtf((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); 308 309 return result; 310 } 311 312 // Calculate square distance between two vectors 313 RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2) 314 { 315 float result = ((v1.x - v2.x)*(v1.x - v2.x) + (v1.y - v2.y)*(v1.y - v2.y)); 316 317 return result; 318 } 319 320 // Calculate angle between two vectors 321 // NOTE: Angle is calculated from origin point (0, 0) 322 RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) 323 { 324 float result = 0.0f; 325 326 float dot = v1.x*v2.x + v1.y*v2.y; 327 float det = v1.x*v2.y - v1.y*v2.x; 328 329 result = atan2f(det, dot); 330 331 return result; 332 } 333 334 // Calculate angle defined by a two vectors line 335 // NOTE: Parameters need to be normalized 336 // Current implementation should be aligned with glm::angle 337 RMAPI float Vector2LineAngle(Vector2 start, Vector2 end) 338 { 339 float result = 0.0f; 340 341 // TODO(10/9/2023): Currently angles move clockwise, determine if this is wanted behavior 342 result = -atan2f(end.y - start.y, end.x - start.x); 343 344 return result; 345 } 346 347 // Scale vector (multiply by value) 348 RMAPI Vector2 Vector2Scale(Vector2 v, float scale) 349 { 350 Vector2 result = { v.x*scale, v.y*scale }; 351 352 return result; 353 } 354 355 // Multiply vector by vector 356 RMAPI Vector2 Vector2Multiply(Vector2 v1, Vector2 v2) 357 { 358 Vector2 result = { v1.x*v2.x, v1.y*v2.y }; 359 360 return result; 361 } 362 363 // Negate vector 364 RMAPI Vector2 Vector2Negate(Vector2 v) 365 { 366 Vector2 result = { -v.x, -v.y }; 367 368 return result; 369 } 370 371 // Divide vector by vector 372 RMAPI Vector2 Vector2Divide(Vector2 v1, Vector2 v2) 373 { 374 Vector2 result = { v1.x/v2.x, v1.y/v2.y }; 375 376 return result; 377 } 378 379 // Normalize provided vector 380 RMAPI Vector2 Vector2Normalize(Vector2 v) 381 { 382 Vector2 result = { 0 }; 383 float length = sqrtf((v.x*v.x) + (v.y*v.y)); 384 385 if (length > 0) 386 { 387 float ilength = 1.0f/length; 388 result.x = v.x*ilength; 389 result.y = v.y*ilength; 390 } 391 392 return result; 393 } 394 395 // Transforms a Vector2 by a given Matrix 396 RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat) 397 { 398 Vector2 result = { 0 }; 399 400 float x = v.x; 401 float y = v.y; 402 float z = 0; 403 404 result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; 405 result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; 406 407 return result; 408 } 409 410 // Calculate linear interpolation between two vectors 411 RMAPI Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount) 412 { 413 Vector2 result = { 0 }; 414 415 result.x = v1.x + amount*(v2.x - v1.x); 416 result.y = v1.y + amount*(v2.y - v1.y); 417 418 return result; 419 } 420 421 // Calculate reflected vector to normal 422 RMAPI Vector2 Vector2Reflect(Vector2 v, Vector2 normal) 423 { 424 Vector2 result = { 0 }; 425 426 float dotProduct = (v.x*normal.x + v.y*normal.y); // Dot product 427 428 result.x = v.x - (2.0f*normal.x)*dotProduct; 429 result.y = v.y - (2.0f*normal.y)*dotProduct; 430 431 return result; 432 } 433 434 // Rotate vector by angle 435 RMAPI Vector2 Vector2Rotate(Vector2 v, float angle) 436 { 437 Vector2 result = { 0 }; 438 439 float cosres = cosf(angle); 440 float sinres = sinf(angle); 441 442 result.x = v.x*cosres - v.y*sinres; 443 result.y = v.x*sinres + v.y*cosres; 444 445 return result; 446 } 447 448 // Move Vector towards target 449 RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance) 450 { 451 Vector2 result = { 0 }; 452 453 float dx = target.x - v.x; 454 float dy = target.y - v.y; 455 float value = (dx*dx) + (dy*dy); 456 457 if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) return target; 458 459 float dist = sqrtf(value); 460 461 result.x = v.x + dx/dist*maxDistance; 462 result.y = v.y + dy/dist*maxDistance; 463 464 return result; 465 } 466 467 // Invert the given vector 468 RMAPI Vector2 Vector2Invert(Vector2 v) 469 { 470 Vector2 result = { 1.0f/v.x, 1.0f/v.y }; 471 472 return result; 473 } 474 475 // Clamp the components of the vector between 476 // min and max values specified by the given vectors 477 RMAPI Vector2 Vector2Clamp(Vector2 v, Vector2 min, Vector2 max) 478 { 479 Vector2 result = { 0 }; 480 481 result.x = fminf(max.x, fmaxf(min.x, v.x)); 482 result.y = fminf(max.y, fmaxf(min.y, v.y)); 483 484 return result; 485 } 486 487 // Clamp the magnitude of the vector between two min and max values 488 RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max) 489 { 490 Vector2 result = v; 491 492 float length = (v.x*v.x) + (v.y*v.y); 493 if (length > 0.0f) 494 { 495 length = sqrtf(length); 496 497 float scale = 1; // By default, 1 as the neutral element. 498 if (length < min) 499 { 500 scale = min/length; 501 } 502 else if (length > max) 503 { 504 scale = max/length; 505 } 506 507 result.x = v.x*scale; 508 result.y = v.y*scale; 509 } 510 511 return result; 512 } 513 514 // Check whether two given vectors are almost equal 515 RMAPI int Vector2Equals(Vector2 p, Vector2 q) 516 { 517 #if !defined(EPSILON) 518 #define EPSILON 0.000001f 519 #endif 520 521 int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 522 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))); 523 524 return result; 525 } 526 527 //---------------------------------------------------------------------------------- 528 // Module Functions Definition - Vector3 math 529 //---------------------------------------------------------------------------------- 530 531 // Vector with components value 0.0f 532 RMAPI Vector3 Vector3Zero(void) 533 { 534 Vector3 result = { 0.0f, 0.0f, 0.0f }; 535 536 return result; 537 } 538 539 // Vector with components value 1.0f 540 RMAPI Vector3 Vector3One(void) 541 { 542 Vector3 result = { 1.0f, 1.0f, 1.0f }; 543 544 return result; 545 } 546 547 // Add two vectors 548 RMAPI Vector3 Vector3Add(Vector3 v1, Vector3 v2) 549 { 550 Vector3 result = { v1.x + v2.x, v1.y + v2.y, v1.z + v2.z }; 551 552 return result; 553 } 554 555 // Add vector and float value 556 RMAPI Vector3 Vector3AddValue(Vector3 v, float add) 557 { 558 Vector3 result = { v.x + add, v.y + add, v.z + add }; 559 560 return result; 561 } 562 563 // Subtract two vectors 564 RMAPI Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) 565 { 566 Vector3 result = { v1.x - v2.x, v1.y - v2.y, v1.z - v2.z }; 567 568 return result; 569 } 570 571 // Subtract vector by float value 572 RMAPI Vector3 Vector3SubtractValue(Vector3 v, float sub) 573 { 574 Vector3 result = { v.x - sub, v.y - sub, v.z - sub }; 575 576 return result; 577 } 578 579 // Multiply vector by scalar 580 RMAPI Vector3 Vector3Scale(Vector3 v, float scalar) 581 { 582 Vector3 result = { v.x*scalar, v.y*scalar, v.z*scalar }; 583 584 return result; 585 } 586 587 // Multiply vector by vector 588 RMAPI Vector3 Vector3Multiply(Vector3 v1, Vector3 v2) 589 { 590 Vector3 result = { v1.x*v2.x, v1.y*v2.y, v1.z*v2.z }; 591 592 return result; 593 } 594 595 // Calculate two vectors cross product 596 RMAPI Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2) 597 { 598 Vector3 result = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x }; 599 600 return result; 601 } 602 603 // Calculate one vector perpendicular vector 604 RMAPI Vector3 Vector3Perpendicular(Vector3 v) 605 { 606 Vector3 result = { 0 }; 607 608 float min = fabsf(v.x); 609 Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f}; 610 611 if (fabsf(v.y) < min) 612 { 613 min = fabsf(v.y); 614 Vector3 tmp = {0.0f, 1.0f, 0.0f}; 615 cardinalAxis = tmp; 616 } 617 618 if (fabsf(v.z) < min) 619 { 620 Vector3 tmp = {0.0f, 0.0f, 1.0f}; 621 cardinalAxis = tmp; 622 } 623 624 // Cross product between vectors 625 result.x = v.y*cardinalAxis.z - v.z*cardinalAxis.y; 626 result.y = v.z*cardinalAxis.x - v.x*cardinalAxis.z; 627 result.z = v.x*cardinalAxis.y - v.y*cardinalAxis.x; 628 629 return result; 630 } 631 632 // Calculate vector length 633 RMAPI float Vector3Length(const Vector3 v) 634 { 635 float result = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); 636 637 return result; 638 } 639 640 // Calculate vector square length 641 RMAPI float Vector3LengthSqr(const Vector3 v) 642 { 643 float result = v.x*v.x + v.y*v.y + v.z*v.z; 644 645 return result; 646 } 647 648 // Calculate two vectors dot product 649 RMAPI float Vector3DotProduct(Vector3 v1, Vector3 v2) 650 { 651 float result = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); 652 653 return result; 654 } 655 656 // Calculate distance between two vectors 657 RMAPI float Vector3Distance(Vector3 v1, Vector3 v2) 658 { 659 float result = 0.0f; 660 661 float dx = v2.x - v1.x; 662 float dy = v2.y - v1.y; 663 float dz = v2.z - v1.z; 664 result = sqrtf(dx*dx + dy*dy + dz*dz); 665 666 return result; 667 } 668 669 // Calculate square distance between two vectors 670 RMAPI float Vector3DistanceSqr(Vector3 v1, Vector3 v2) 671 { 672 float result = 0.0f; 673 674 float dx = v2.x - v1.x; 675 float dy = v2.y - v1.y; 676 float dz = v2.z - v1.z; 677 result = dx*dx + dy*dy + dz*dz; 678 679 return result; 680 } 681 682 // Calculate angle between two vectors 683 RMAPI float Vector3Angle(Vector3 v1, Vector3 v2) 684 { 685 float result = 0.0f; 686 687 Vector3 cross = { v1.y*v2.z - v1.z*v2.y, v1.z*v2.x - v1.x*v2.z, v1.x*v2.y - v1.y*v2.x }; 688 float len = sqrtf(cross.x*cross.x + cross.y*cross.y + cross.z*cross.z); 689 float dot = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); 690 result = atan2f(len, dot); 691 692 return result; 693 } 694 695 // Negate provided vector (invert direction) 696 RMAPI Vector3 Vector3Negate(Vector3 v) 697 { 698 Vector3 result = { -v.x, -v.y, -v.z }; 699 700 return result; 701 } 702 703 // Divide vector by vector 704 RMAPI Vector3 Vector3Divide(Vector3 v1, Vector3 v2) 705 { 706 Vector3 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z }; 707 708 return result; 709 } 710 711 // Normalize provided vector 712 RMAPI Vector3 Vector3Normalize(Vector3 v) 713 { 714 Vector3 result = v; 715 716 float length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); 717 if (length != 0.0f) 718 { 719 float ilength = 1.0f/length; 720 721 result.x *= ilength; 722 result.y *= ilength; 723 result.z *= ilength; 724 } 725 726 return result; 727 } 728 729 //Calculate the projection of the vector v1 on to v2 730 RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2) 731 { 732 Vector3 result = { 0 }; 733 734 float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); 735 float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z); 736 737 float mag = v1dv2/v2dv2; 738 739 result.x = v2.x*mag; 740 result.y = v2.y*mag; 741 result.z = v2.z*mag; 742 743 return result; 744 } 745 746 //Calculate the rejection of the vector v1 on to v2 747 RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2) 748 { 749 Vector3 result = { 0 }; 750 751 float v1dv2 = (v1.x*v2.x + v1.y*v2.y + v1.z*v2.z); 752 float v2dv2 = (v2.x*v2.x + v2.y*v2.y + v2.z*v2.z); 753 754 float mag = v1dv2/v2dv2; 755 756 result.x = v1.x - (v2.x*mag); 757 result.y = v1.y - (v2.y*mag); 758 result.z = v1.z - (v2.z*mag); 759 760 return result; 761 } 762 763 // Orthonormalize provided vectors 764 // Makes vectors normalized and orthogonal to each other 765 // Gram-Schmidt function implementation 766 RMAPI void Vector3OrthoNormalize(Vector3 *v1, Vector3 *v2) 767 { 768 float length = 0.0f; 769 float ilength = 0.0f; 770 771 // Vector3Normalize(*v1); 772 Vector3 v = *v1; 773 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); 774 if (length == 0.0f) length = 1.0f; 775 ilength = 1.0f/length; 776 v1->x *= ilength; 777 v1->y *= ilength; 778 v1->z *= ilength; 779 780 // Vector3CrossProduct(*v1, *v2) 781 Vector3 vn1 = { v1->y*v2->z - v1->z*v2->y, v1->z*v2->x - v1->x*v2->z, v1->x*v2->y - v1->y*v2->x }; 782 783 // Vector3Normalize(vn1); 784 v = vn1; 785 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); 786 if (length == 0.0f) length = 1.0f; 787 ilength = 1.0f/length; 788 vn1.x *= ilength; 789 vn1.y *= ilength; 790 vn1.z *= ilength; 791 792 // Vector3CrossProduct(vn1, *v1) 793 Vector3 vn2 = { vn1.y*v1->z - vn1.z*v1->y, vn1.z*v1->x - vn1.x*v1->z, vn1.x*v1->y - vn1.y*v1->x }; 794 795 *v2 = vn2; 796 } 797 798 // Transforms a Vector3 by a given Matrix 799 RMAPI Vector3 Vector3Transform(Vector3 v, Matrix mat) 800 { 801 Vector3 result = { 0 }; 802 803 float x = v.x; 804 float y = v.y; 805 float z = v.z; 806 807 result.x = mat.m0*x + mat.m4*y + mat.m8*z + mat.m12; 808 result.y = mat.m1*x + mat.m5*y + mat.m9*z + mat.m13; 809 result.z = mat.m2*x + mat.m6*y + mat.m10*z + mat.m14; 810 811 return result; 812 } 813 814 // Transform a vector by quaternion rotation 815 RMAPI Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q) 816 { 817 Vector3 result = { 0 }; 818 819 result.x = v.x*(q.x*q.x + q.w*q.w - q.y*q.y - q.z*q.z) + v.y*(2*q.x*q.y - 2*q.w*q.z) + v.z*(2*q.x*q.z + 2*q.w*q.y); 820 result.y = v.x*(2*q.w*q.z + 2*q.x*q.y) + v.y*(q.w*q.w - q.x*q.x + q.y*q.y - q.z*q.z) + v.z*(-2*q.w*q.x + 2*q.y*q.z); 821 result.z = v.x*(-2*q.w*q.y + 2*q.x*q.z) + v.y*(2*q.w*q.x + 2*q.y*q.z)+ v.z*(q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z); 822 823 return result; 824 } 825 826 // Rotates a vector around an axis 827 RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle) 828 { 829 // Using Euler-Rodrigues Formula 830 // Ref.: https://en.wikipedia.org/w/index.php?title=Euler%E2%80%93Rodrigues_formula 831 832 Vector3 result = v; 833 834 // Vector3Normalize(axis); 835 float length = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); 836 if (length == 0.0f) length = 1.0f; 837 float ilength = 1.0f/length; 838 axis.x *= ilength; 839 axis.y *= ilength; 840 axis.z *= ilength; 841 842 angle /= 2.0f; 843 float a = sinf(angle); 844 float b = axis.x*a; 845 float c = axis.y*a; 846 float d = axis.z*a; 847 a = cosf(angle); 848 Vector3 w = { b, c, d }; 849 850 // Vector3CrossProduct(w, v) 851 Vector3 wv = { w.y*v.z - w.z*v.y, w.z*v.x - w.x*v.z, w.x*v.y - w.y*v.x }; 852 853 // Vector3CrossProduct(w, wv) 854 Vector3 wwv = { w.y*wv.z - w.z*wv.y, w.z*wv.x - w.x*wv.z, w.x*wv.y - w.y*wv.x }; 855 856 // Vector3Scale(wv, 2*a) 857 a *= 2; 858 wv.x *= a; 859 wv.y *= a; 860 wv.z *= a; 861 862 // Vector3Scale(wwv, 2) 863 wwv.x *= 2; 864 wwv.y *= 2; 865 wwv.z *= 2; 866 867 result.x += wv.x; 868 result.y += wv.y; 869 result.z += wv.z; 870 871 result.x += wwv.x; 872 result.y += wwv.y; 873 result.z += wwv.z; 874 875 return result; 876 } 877 878 // Calculate linear interpolation between two vectors 879 RMAPI Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount) 880 { 881 Vector3 result = { 0 }; 882 883 result.x = v1.x + amount*(v2.x - v1.x); 884 result.y = v1.y + amount*(v2.y - v1.y); 885 result.z = v1.z + amount*(v2.z - v1.z); 886 887 return result; 888 } 889 890 // Calculate reflected vector to normal 891 RMAPI Vector3 Vector3Reflect(Vector3 v, Vector3 normal) 892 { 893 Vector3 result = { 0 }; 894 895 // I is the original vector 896 // N is the normal of the incident plane 897 // R = I - (2*N*(DotProduct[I, N])) 898 899 float dotProduct = (v.x*normal.x + v.y*normal.y + v.z*normal.z); 900 901 result.x = v.x - (2.0f*normal.x)*dotProduct; 902 result.y = v.y - (2.0f*normal.y)*dotProduct; 903 result.z = v.z - (2.0f*normal.z)*dotProduct; 904 905 return result; 906 } 907 908 // Get min value for each pair of components 909 RMAPI Vector3 Vector3Min(Vector3 v1, Vector3 v2) 910 { 911 Vector3 result = { 0 }; 912 913 result.x = fminf(v1.x, v2.x); 914 result.y = fminf(v1.y, v2.y); 915 result.z = fminf(v1.z, v2.z); 916 917 return result; 918 } 919 920 // Get max value for each pair of components 921 RMAPI Vector3 Vector3Max(Vector3 v1, Vector3 v2) 922 { 923 Vector3 result = { 0 }; 924 925 result.x = fmaxf(v1.x, v2.x); 926 result.y = fmaxf(v1.y, v2.y); 927 result.z = fmaxf(v1.z, v2.z); 928 929 return result; 930 } 931 932 // Compute barycenter coordinates (u, v, w) for point p with respect to triangle (a, b, c) 933 // NOTE: Assumes P is on the plane of the triangle 934 RMAPI Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) 935 { 936 Vector3 result = { 0 }; 937 938 Vector3 v0 = { b.x - a.x, b.y - a.y, b.z - a.z }; // Vector3Subtract(b, a) 939 Vector3 v1 = { c.x - a.x, c.y - a.y, c.z - a.z }; // Vector3Subtract(c, a) 940 Vector3 v2 = { p.x - a.x, p.y - a.y, p.z - a.z }; // Vector3Subtract(p, a) 941 float d00 = (v0.x*v0.x + v0.y*v0.y + v0.z*v0.z); // Vector3DotProduct(v0, v0) 942 float d01 = (v0.x*v1.x + v0.y*v1.y + v0.z*v1.z); // Vector3DotProduct(v0, v1) 943 float d11 = (v1.x*v1.x + v1.y*v1.y + v1.z*v1.z); // Vector3DotProduct(v1, v1) 944 float d20 = (v2.x*v0.x + v2.y*v0.y + v2.z*v0.z); // Vector3DotProduct(v2, v0) 945 float d21 = (v2.x*v1.x + v2.y*v1.y + v2.z*v1.z); // Vector3DotProduct(v2, v1) 946 947 float denom = d00*d11 - d01*d01; 948 949 result.y = (d11*d20 - d01*d21)/denom; 950 result.z = (d00*d21 - d01*d20)/denom; 951 result.x = 1.0f - (result.z + result.y); 952 953 return result; 954 } 955 956 // Projects a Vector3 from screen space into object space 957 // NOTE: We are avoiding calling other raymath functions despite available 958 RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view) 959 { 960 Vector3 result = { 0 }; 961 962 // Calculate unprojected matrix (multiply view matrix by projection matrix) and invert it 963 Matrix matViewProj = { // MatrixMultiply(view, projection); 964 view.m0*projection.m0 + view.m1*projection.m4 + view.m2*projection.m8 + view.m3*projection.m12, 965 view.m0*projection.m1 + view.m1*projection.m5 + view.m2*projection.m9 + view.m3*projection.m13, 966 view.m0*projection.m2 + view.m1*projection.m6 + view.m2*projection.m10 + view.m3*projection.m14, 967 view.m0*projection.m3 + view.m1*projection.m7 + view.m2*projection.m11 + view.m3*projection.m15, 968 view.m4*projection.m0 + view.m5*projection.m4 + view.m6*projection.m8 + view.m7*projection.m12, 969 view.m4*projection.m1 + view.m5*projection.m5 + view.m6*projection.m9 + view.m7*projection.m13, 970 view.m4*projection.m2 + view.m5*projection.m6 + view.m6*projection.m10 + view.m7*projection.m14, 971 view.m4*projection.m3 + view.m5*projection.m7 + view.m6*projection.m11 + view.m7*projection.m15, 972 view.m8*projection.m0 + view.m9*projection.m4 + view.m10*projection.m8 + view.m11*projection.m12, 973 view.m8*projection.m1 + view.m9*projection.m5 + view.m10*projection.m9 + view.m11*projection.m13, 974 view.m8*projection.m2 + view.m9*projection.m6 + view.m10*projection.m10 + view.m11*projection.m14, 975 view.m8*projection.m3 + view.m9*projection.m7 + view.m10*projection.m11 + view.m11*projection.m15, 976 view.m12*projection.m0 + view.m13*projection.m4 + view.m14*projection.m8 + view.m15*projection.m12, 977 view.m12*projection.m1 + view.m13*projection.m5 + view.m14*projection.m9 + view.m15*projection.m13, 978 view.m12*projection.m2 + view.m13*projection.m6 + view.m14*projection.m10 + view.m15*projection.m14, 979 view.m12*projection.m3 + view.m13*projection.m7 + view.m14*projection.m11 + view.m15*projection.m15 }; 980 981 // Calculate inverted matrix -> MatrixInvert(matViewProj); 982 // Cache the matrix values (speed optimization) 983 float a00 = matViewProj.m0, a01 = matViewProj.m1, a02 = matViewProj.m2, a03 = matViewProj.m3; 984 float a10 = matViewProj.m4, a11 = matViewProj.m5, a12 = matViewProj.m6, a13 = matViewProj.m7; 985 float a20 = matViewProj.m8, a21 = matViewProj.m9, a22 = matViewProj.m10, a23 = matViewProj.m11; 986 float a30 = matViewProj.m12, a31 = matViewProj.m13, a32 = matViewProj.m14, a33 = matViewProj.m15; 987 988 float b00 = a00*a11 - a01*a10; 989 float b01 = a00*a12 - a02*a10; 990 float b02 = a00*a13 - a03*a10; 991 float b03 = a01*a12 - a02*a11; 992 float b04 = a01*a13 - a03*a11; 993 float b05 = a02*a13 - a03*a12; 994 float b06 = a20*a31 - a21*a30; 995 float b07 = a20*a32 - a22*a30; 996 float b08 = a20*a33 - a23*a30; 997 float b09 = a21*a32 - a22*a31; 998 float b10 = a21*a33 - a23*a31; 999 float b11 = a22*a33 - a23*a32; 1000 1001 // Calculate the invert determinant (inlined to avoid double-caching) 1002 float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); 1003 1004 Matrix matViewProjInv = { 1005 (a11*b11 - a12*b10 + a13*b09)*invDet, 1006 (-a01*b11 + a02*b10 - a03*b09)*invDet, 1007 (a31*b05 - a32*b04 + a33*b03)*invDet, 1008 (-a21*b05 + a22*b04 - a23*b03)*invDet, 1009 (-a10*b11 + a12*b08 - a13*b07)*invDet, 1010 (a00*b11 - a02*b08 + a03*b07)*invDet, 1011 (-a30*b05 + a32*b02 - a33*b01)*invDet, 1012 (a20*b05 - a22*b02 + a23*b01)*invDet, 1013 (a10*b10 - a11*b08 + a13*b06)*invDet, 1014 (-a00*b10 + a01*b08 - a03*b06)*invDet, 1015 (a30*b04 - a31*b02 + a33*b00)*invDet, 1016 (-a20*b04 + a21*b02 - a23*b00)*invDet, 1017 (-a10*b09 + a11*b07 - a12*b06)*invDet, 1018 (a00*b09 - a01*b07 + a02*b06)*invDet, 1019 (-a30*b03 + a31*b01 - a32*b00)*invDet, 1020 (a20*b03 - a21*b01 + a22*b00)*invDet }; 1021 1022 // Create quaternion from source point 1023 Quaternion quat = { source.x, source.y, source.z, 1.0f }; 1024 1025 // Multiply quat point by unprojecte matrix 1026 Quaternion qtransformed = { // QuaternionTransform(quat, matViewProjInv) 1027 matViewProjInv.m0*quat.x + matViewProjInv.m4*quat.y + matViewProjInv.m8*quat.z + matViewProjInv.m12*quat.w, 1028 matViewProjInv.m1*quat.x + matViewProjInv.m5*quat.y + matViewProjInv.m9*quat.z + matViewProjInv.m13*quat.w, 1029 matViewProjInv.m2*quat.x + matViewProjInv.m6*quat.y + matViewProjInv.m10*quat.z + matViewProjInv.m14*quat.w, 1030 matViewProjInv.m3*quat.x + matViewProjInv.m7*quat.y + matViewProjInv.m11*quat.z + matViewProjInv.m15*quat.w }; 1031 1032 // Normalized world points in vectors 1033 result.x = qtransformed.x/qtransformed.w; 1034 result.y = qtransformed.y/qtransformed.w; 1035 result.z = qtransformed.z/qtransformed.w; 1036 1037 return result; 1038 } 1039 1040 // Get Vector3 as float array 1041 RMAPI float3 Vector3ToFloatV(Vector3 v) 1042 { 1043 float3 buffer = { 0 }; 1044 1045 buffer.v[0] = v.x; 1046 buffer.v[1] = v.y; 1047 buffer.v[2] = v.z; 1048 1049 return buffer; 1050 } 1051 1052 // Invert the given vector 1053 RMAPI Vector3 Vector3Invert(Vector3 v) 1054 { 1055 Vector3 result = { 1.0f/v.x, 1.0f/v.y, 1.0f/v.z }; 1056 1057 return result; 1058 } 1059 1060 // Clamp the components of the vector between 1061 // min and max values specified by the given vectors 1062 RMAPI Vector3 Vector3Clamp(Vector3 v, Vector3 min, Vector3 max) 1063 { 1064 Vector3 result = { 0 }; 1065 1066 result.x = fminf(max.x, fmaxf(min.x, v.x)); 1067 result.y = fminf(max.y, fmaxf(min.y, v.y)); 1068 result.z = fminf(max.z, fmaxf(min.z, v.z)); 1069 1070 return result; 1071 } 1072 1073 // Clamp the magnitude of the vector between two values 1074 RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max) 1075 { 1076 Vector3 result = v; 1077 1078 float length = (v.x*v.x) + (v.y*v.y) + (v.z*v.z); 1079 if (length > 0.0f) 1080 { 1081 length = sqrtf(length); 1082 1083 float scale = 1; // By default, 1 as the neutral element. 1084 if (length < min) 1085 { 1086 scale = min/length; 1087 } 1088 else if (length > max) 1089 { 1090 scale = max/length; 1091 } 1092 1093 result.x = v.x*scale; 1094 result.y = v.y*scale; 1095 result.z = v.z*scale; 1096 } 1097 1098 return result; 1099 } 1100 1101 // Check whether two given vectors are almost equal 1102 RMAPI int Vector3Equals(Vector3 p, Vector3 q) 1103 { 1104 #if !defined(EPSILON) 1105 #define EPSILON 0.000001f 1106 #endif 1107 1108 int result = ((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 1109 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && 1110 ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))); 1111 1112 return result; 1113 } 1114 1115 // Compute the direction of a refracted ray 1116 // v: normalized direction of the incoming ray 1117 // n: normalized normal vector of the interface of two optical media 1118 // r: ratio of the refractive index of the medium from where the ray comes 1119 // to the refractive index of the medium on the other side of the surface 1120 RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r) 1121 { 1122 Vector3 result = { 0 }; 1123 1124 float dot = v.x*n.x + v.y*n.y + v.z*n.z; 1125 float d = 1.0f - r*r*(1.0f - dot*dot); 1126 1127 if (d >= 0.0f) 1128 { 1129 d = sqrtf(d); 1130 v.x = r*v.x - (r*dot + d)*n.x; 1131 v.y = r*v.y - (r*dot + d)*n.y; 1132 v.z = r*v.z - (r*dot + d)*n.z; 1133 1134 result = v; 1135 } 1136 1137 return result; 1138 } 1139 1140 //---------------------------------------------------------------------------------- 1141 // Module Functions Definition - Matrix math 1142 //---------------------------------------------------------------------------------- 1143 1144 // Compute matrix determinant 1145 RMAPI float MatrixDeterminant(Matrix mat) 1146 { 1147 float result = 0.0f; 1148 1149 // Cache the matrix values (speed optimization) 1150 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; 1151 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; 1152 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; 1153 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; 1154 1155 result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + a10*a31*a22*a03 + 1156 a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + a20*a31*a02*a13 + 1157 a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + a00*a21*a32*a13 + 1158 a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + a00*a31*a12*a23 + 1159 a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + a10*a21*a02*a33 + 1160 a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + a00*a11*a22*a33; 1161 1162 return result; 1163 } 1164 1165 // Get the trace of the matrix (sum of the values along the diagonal) 1166 RMAPI float MatrixTrace(Matrix mat) 1167 { 1168 float result = (mat.m0 + mat.m5 + mat.m10 + mat.m15); 1169 1170 return result; 1171 } 1172 1173 // Transposes provided matrix 1174 RMAPI Matrix MatrixTranspose(Matrix mat) 1175 { 1176 Matrix result = { 0 }; 1177 1178 result.m0 = mat.m0; 1179 result.m1 = mat.m4; 1180 result.m2 = mat.m8; 1181 result.m3 = mat.m12; 1182 result.m4 = mat.m1; 1183 result.m5 = mat.m5; 1184 result.m6 = mat.m9; 1185 result.m7 = mat.m13; 1186 result.m8 = mat.m2; 1187 result.m9 = mat.m6; 1188 result.m10 = mat.m10; 1189 result.m11 = mat.m14; 1190 result.m12 = mat.m3; 1191 result.m13 = mat.m7; 1192 result.m14 = mat.m11; 1193 result.m15 = mat.m15; 1194 1195 return result; 1196 } 1197 1198 // Invert provided matrix 1199 RMAPI Matrix MatrixInvert(Matrix mat) 1200 { 1201 Matrix result = { 0 }; 1202 1203 // Cache the matrix values (speed optimization) 1204 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; 1205 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; 1206 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; 1207 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; 1208 1209 float b00 = a00*a11 - a01*a10; 1210 float b01 = a00*a12 - a02*a10; 1211 float b02 = a00*a13 - a03*a10; 1212 float b03 = a01*a12 - a02*a11; 1213 float b04 = a01*a13 - a03*a11; 1214 float b05 = a02*a13 - a03*a12; 1215 float b06 = a20*a31 - a21*a30; 1216 float b07 = a20*a32 - a22*a30; 1217 float b08 = a20*a33 - a23*a30; 1218 float b09 = a21*a32 - a22*a31; 1219 float b10 = a21*a33 - a23*a31; 1220 float b11 = a22*a33 - a23*a32; 1221 1222 // Calculate the invert determinant (inlined to avoid double-caching) 1223 float invDet = 1.0f/(b00*b11 - b01*b10 + b02*b09 + b03*b08 - b04*b07 + b05*b06); 1224 1225 result.m0 = (a11*b11 - a12*b10 + a13*b09)*invDet; 1226 result.m1 = (-a01*b11 + a02*b10 - a03*b09)*invDet; 1227 result.m2 = (a31*b05 - a32*b04 + a33*b03)*invDet; 1228 result.m3 = (-a21*b05 + a22*b04 - a23*b03)*invDet; 1229 result.m4 = (-a10*b11 + a12*b08 - a13*b07)*invDet; 1230 result.m5 = (a00*b11 - a02*b08 + a03*b07)*invDet; 1231 result.m6 = (-a30*b05 + a32*b02 - a33*b01)*invDet; 1232 result.m7 = (a20*b05 - a22*b02 + a23*b01)*invDet; 1233 result.m8 = (a10*b10 - a11*b08 + a13*b06)*invDet; 1234 result.m9 = (-a00*b10 + a01*b08 - a03*b06)*invDet; 1235 result.m10 = (a30*b04 - a31*b02 + a33*b00)*invDet; 1236 result.m11 = (-a20*b04 + a21*b02 - a23*b00)*invDet; 1237 result.m12 = (-a10*b09 + a11*b07 - a12*b06)*invDet; 1238 result.m13 = (a00*b09 - a01*b07 + a02*b06)*invDet; 1239 result.m14 = (-a30*b03 + a31*b01 - a32*b00)*invDet; 1240 result.m15 = (a20*b03 - a21*b01 + a22*b00)*invDet; 1241 1242 return result; 1243 } 1244 1245 // Get identity matrix 1246 RMAPI Matrix MatrixIdentity(void) 1247 { 1248 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 1249 0.0f, 1.0f, 0.0f, 0.0f, 1250 0.0f, 0.0f, 1.0f, 0.0f, 1251 0.0f, 0.0f, 0.0f, 1.0f }; 1252 1253 return result; 1254 } 1255 1256 // Add two matrices 1257 RMAPI Matrix MatrixAdd(Matrix left, Matrix right) 1258 { 1259 Matrix result = { 0 }; 1260 1261 result.m0 = left.m0 + right.m0; 1262 result.m1 = left.m1 + right.m1; 1263 result.m2 = left.m2 + right.m2; 1264 result.m3 = left.m3 + right.m3; 1265 result.m4 = left.m4 + right.m4; 1266 result.m5 = left.m5 + right.m5; 1267 result.m6 = left.m6 + right.m6; 1268 result.m7 = left.m7 + right.m7; 1269 result.m8 = left.m8 + right.m8; 1270 result.m9 = left.m9 + right.m9; 1271 result.m10 = left.m10 + right.m10; 1272 result.m11 = left.m11 + right.m11; 1273 result.m12 = left.m12 + right.m12; 1274 result.m13 = left.m13 + right.m13; 1275 result.m14 = left.m14 + right.m14; 1276 result.m15 = left.m15 + right.m15; 1277 1278 return result; 1279 } 1280 1281 // Subtract two matrices (left - right) 1282 RMAPI Matrix MatrixSubtract(Matrix left, Matrix right) 1283 { 1284 Matrix result = { 0 }; 1285 1286 result.m0 = left.m0 - right.m0; 1287 result.m1 = left.m1 - right.m1; 1288 result.m2 = left.m2 - right.m2; 1289 result.m3 = left.m3 - right.m3; 1290 result.m4 = left.m4 - right.m4; 1291 result.m5 = left.m5 - right.m5; 1292 result.m6 = left.m6 - right.m6; 1293 result.m7 = left.m7 - right.m7; 1294 result.m8 = left.m8 - right.m8; 1295 result.m9 = left.m9 - right.m9; 1296 result.m10 = left.m10 - right.m10; 1297 result.m11 = left.m11 - right.m11; 1298 result.m12 = left.m12 - right.m12; 1299 result.m13 = left.m13 - right.m13; 1300 result.m14 = left.m14 - right.m14; 1301 result.m15 = left.m15 - right.m15; 1302 1303 return result; 1304 } 1305 1306 // Get two matrix multiplication 1307 // NOTE: When multiplying matrices... the order matters! 1308 RMAPI Matrix MatrixMultiply(Matrix left, Matrix right) 1309 { 1310 Matrix result = { 0 }; 1311 1312 result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; 1313 result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; 1314 result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; 1315 result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; 1316 result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; 1317 result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; 1318 result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; 1319 result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; 1320 result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; 1321 result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; 1322 result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; 1323 result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; 1324 result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; 1325 result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; 1326 result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; 1327 result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; 1328 1329 return result; 1330 } 1331 1332 // Get translation matrix 1333 RMAPI Matrix MatrixTranslate(float x, float y, float z) 1334 { 1335 Matrix result = { 1.0f, 0.0f, 0.0f, x, 1336 0.0f, 1.0f, 0.0f, y, 1337 0.0f, 0.0f, 1.0f, z, 1338 0.0f, 0.0f, 0.0f, 1.0f }; 1339 1340 return result; 1341 } 1342 1343 // Create rotation matrix from axis and angle 1344 // NOTE: Angle should be provided in radians 1345 RMAPI Matrix MatrixRotate(Vector3 axis, float angle) 1346 { 1347 Matrix result = { 0 }; 1348 1349 float x = axis.x, y = axis.y, z = axis.z; 1350 1351 float lengthSquared = x*x + y*y + z*z; 1352 1353 if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) 1354 { 1355 float ilength = 1.0f/sqrtf(lengthSquared); 1356 x *= ilength; 1357 y *= ilength; 1358 z *= ilength; 1359 } 1360 1361 float sinres = sinf(angle); 1362 float cosres = cosf(angle); 1363 float t = 1.0f - cosres; 1364 1365 result.m0 = x*x*t + cosres; 1366 result.m1 = y*x*t + z*sinres; 1367 result.m2 = z*x*t - y*sinres; 1368 result.m3 = 0.0f; 1369 1370 result.m4 = x*y*t - z*sinres; 1371 result.m5 = y*y*t + cosres; 1372 result.m6 = z*y*t + x*sinres; 1373 result.m7 = 0.0f; 1374 1375 result.m8 = x*z*t + y*sinres; 1376 result.m9 = y*z*t - x*sinres; 1377 result.m10 = z*z*t + cosres; 1378 result.m11 = 0.0f; 1379 1380 result.m12 = 0.0f; 1381 result.m13 = 0.0f; 1382 result.m14 = 0.0f; 1383 result.m15 = 1.0f; 1384 1385 return result; 1386 } 1387 1388 // Get x-rotation matrix 1389 // NOTE: Angle must be provided in radians 1390 RMAPI Matrix MatrixRotateX(float angle) 1391 { 1392 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 1393 0.0f, 1.0f, 0.0f, 0.0f, 1394 0.0f, 0.0f, 1.0f, 0.0f, 1395 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() 1396 1397 float cosres = cosf(angle); 1398 float sinres = sinf(angle); 1399 1400 result.m5 = cosres; 1401 result.m6 = sinres; 1402 result.m9 = -sinres; 1403 result.m10 = cosres; 1404 1405 return result; 1406 } 1407 1408 // Get y-rotation matrix 1409 // NOTE: Angle must be provided in radians 1410 RMAPI Matrix MatrixRotateY(float angle) 1411 { 1412 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 1413 0.0f, 1.0f, 0.0f, 0.0f, 1414 0.0f, 0.0f, 1.0f, 0.0f, 1415 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() 1416 1417 float cosres = cosf(angle); 1418 float sinres = sinf(angle); 1419 1420 result.m0 = cosres; 1421 result.m2 = -sinres; 1422 result.m8 = sinres; 1423 result.m10 = cosres; 1424 1425 return result; 1426 } 1427 1428 // Get z-rotation matrix 1429 // NOTE: Angle must be provided in radians 1430 RMAPI Matrix MatrixRotateZ(float angle) 1431 { 1432 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 1433 0.0f, 1.0f, 0.0f, 0.0f, 1434 0.0f, 0.0f, 1.0f, 0.0f, 1435 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() 1436 1437 float cosres = cosf(angle); 1438 float sinres = sinf(angle); 1439 1440 result.m0 = cosres; 1441 result.m1 = sinres; 1442 result.m4 = -sinres; 1443 result.m5 = cosres; 1444 1445 return result; 1446 } 1447 1448 1449 // Get xyz-rotation matrix 1450 // NOTE: Angle must be provided in radians 1451 RMAPI Matrix MatrixRotateXYZ(Vector3 angle) 1452 { 1453 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 1454 0.0f, 1.0f, 0.0f, 0.0f, 1455 0.0f, 0.0f, 1.0f, 0.0f, 1456 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() 1457 1458 float cosz = cosf(-angle.z); 1459 float sinz = sinf(-angle.z); 1460 float cosy = cosf(-angle.y); 1461 float siny = sinf(-angle.y); 1462 float cosx = cosf(-angle.x); 1463 float sinx = sinf(-angle.x); 1464 1465 result.m0 = cosz*cosy; 1466 result.m1 = (cosz*siny*sinx) - (sinz*cosx); 1467 result.m2 = (cosz*siny*cosx) + (sinz*sinx); 1468 1469 result.m4 = sinz*cosy; 1470 result.m5 = (sinz*siny*sinx) + (cosz*cosx); 1471 result.m6 = (sinz*siny*cosx) - (cosz*sinx); 1472 1473 result.m8 = -siny; 1474 result.m9 = cosy*sinx; 1475 result.m10= cosy*cosx; 1476 1477 return result; 1478 } 1479 1480 // Get zyx-rotation matrix 1481 // NOTE: Angle must be provided in radians 1482 RMAPI Matrix MatrixRotateZYX(Vector3 angle) 1483 { 1484 Matrix result = { 0 }; 1485 1486 float cz = cosf(angle.z); 1487 float sz = sinf(angle.z); 1488 float cy = cosf(angle.y); 1489 float sy = sinf(angle.y); 1490 float cx = cosf(angle.x); 1491 float sx = sinf(angle.x); 1492 1493 result.m0 = cz*cy; 1494 result.m4 = cz*sy*sx - cx*sz; 1495 result.m8 = sz*sx + cz*cx*sy; 1496 result.m12 = 0; 1497 1498 result.m1 = cy*sz; 1499 result.m5 = cz*cx + sz*sy*sx; 1500 result.m9 = cx*sz*sy - cz*sx; 1501 result.m13 = 0; 1502 1503 result.m2 = -sy; 1504 result.m6 = cy*sx; 1505 result.m10 = cy*cx; 1506 result.m14 = 0; 1507 1508 result.m3 = 0; 1509 result.m7 = 0; 1510 result.m11 = 0; 1511 result.m15 = 1; 1512 1513 return result; 1514 } 1515 1516 // Get scaling matrix 1517 RMAPI Matrix MatrixScale(float x, float y, float z) 1518 { 1519 Matrix result = { x, 0.0f, 0.0f, 0.0f, 1520 0.0f, y, 0.0f, 0.0f, 1521 0.0f, 0.0f, z, 0.0f, 1522 0.0f, 0.0f, 0.0f, 1.0f }; 1523 1524 return result; 1525 } 1526 1527 // Get perspective projection matrix 1528 RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, double near, double far) 1529 { 1530 Matrix result = { 0 }; 1531 1532 float rl = (float)(right - left); 1533 float tb = (float)(top - bottom); 1534 float fn = (float)(far - near); 1535 1536 result.m0 = ((float)near*2.0f)/rl; 1537 result.m1 = 0.0f; 1538 result.m2 = 0.0f; 1539 result.m3 = 0.0f; 1540 1541 result.m4 = 0.0f; 1542 result.m5 = ((float)near*2.0f)/tb; 1543 result.m6 = 0.0f; 1544 result.m7 = 0.0f; 1545 1546 result.m8 = ((float)right + (float)left)/rl; 1547 result.m9 = ((float)top + (float)bottom)/tb; 1548 result.m10 = -((float)far + (float)near)/fn; 1549 result.m11 = -1.0f; 1550 1551 result.m12 = 0.0f; 1552 result.m13 = 0.0f; 1553 result.m14 = -((float)far*(float)near*2.0f)/fn; 1554 result.m15 = 0.0f; 1555 1556 return result; 1557 } 1558 1559 // Get perspective projection matrix 1560 // NOTE: Fovy angle must be provided in radians 1561 RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, double farPlane) 1562 { 1563 Matrix result = { 0 }; 1564 1565 double top = nearPlane*tan(fovY*0.5); 1566 double bottom = -top; 1567 double right = top*aspect; 1568 double left = -right; 1569 1570 // MatrixFrustum(-right, right, -top, top, near, far); 1571 float rl = (float)(right - left); 1572 float tb = (float)(top - bottom); 1573 float fn = (float)(farPlane - nearPlane); 1574 1575 result.m0 = ((float)nearPlane*2.0f)/rl; 1576 result.m5 = ((float)nearPlane*2.0f)/tb; 1577 result.m8 = ((float)right + (float)left)/rl; 1578 result.m9 = ((float)top + (float)bottom)/tb; 1579 result.m10 = -((float)farPlane + (float)nearPlane)/fn; 1580 result.m11 = -1.0f; 1581 result.m14 = -((float)farPlane*(float)nearPlane*2.0f)/fn; 1582 1583 return result; 1584 } 1585 1586 // Get orthographic projection matrix 1587 RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, double nearPlane, double farPlane) 1588 { 1589 Matrix result = { 0 }; 1590 1591 float rl = (float)(right - left); 1592 float tb = (float)(top - bottom); 1593 float fn = (float)(farPlane - nearPlane); 1594 1595 result.m0 = 2.0f/rl; 1596 result.m1 = 0.0f; 1597 result.m2 = 0.0f; 1598 result.m3 = 0.0f; 1599 result.m4 = 0.0f; 1600 result.m5 = 2.0f/tb; 1601 result.m6 = 0.0f; 1602 result.m7 = 0.0f; 1603 result.m8 = 0.0f; 1604 result.m9 = 0.0f; 1605 result.m10 = -2.0f/fn; 1606 result.m11 = 0.0f; 1607 result.m12 = -((float)left + (float)right)/rl; 1608 result.m13 = -((float)top + (float)bottom)/tb; 1609 result.m14 = -((float)farPlane + (float)nearPlane)/fn; 1610 result.m15 = 1.0f; 1611 1612 return result; 1613 } 1614 1615 // Get camera look-at matrix (view matrix) 1616 RMAPI Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) 1617 { 1618 Matrix result = { 0 }; 1619 1620 float length = 0.0f; 1621 float ilength = 0.0f; 1622 1623 // Vector3Subtract(eye, target) 1624 Vector3 vz = { eye.x - target.x, eye.y - target.y, eye.z - target.z }; 1625 1626 // Vector3Normalize(vz) 1627 Vector3 v = vz; 1628 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); 1629 if (length == 0.0f) length = 1.0f; 1630 ilength = 1.0f/length; 1631 vz.x *= ilength; 1632 vz.y *= ilength; 1633 vz.z *= ilength; 1634 1635 // Vector3CrossProduct(up, vz) 1636 Vector3 vx = { up.y*vz.z - up.z*vz.y, up.z*vz.x - up.x*vz.z, up.x*vz.y - up.y*vz.x }; 1637 1638 // Vector3Normalize(x) 1639 v = vx; 1640 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); 1641 if (length == 0.0f) length = 1.0f; 1642 ilength = 1.0f/length; 1643 vx.x *= ilength; 1644 vx.y *= ilength; 1645 vx.z *= ilength; 1646 1647 // Vector3CrossProduct(vz, vx) 1648 Vector3 vy = { vz.y*vx.z - vz.z*vx.y, vz.z*vx.x - vz.x*vx.z, vz.x*vx.y - vz.y*vx.x }; 1649 1650 result.m0 = vx.x; 1651 result.m1 = vy.x; 1652 result.m2 = vz.x; 1653 result.m3 = 0.0f; 1654 result.m4 = vx.y; 1655 result.m5 = vy.y; 1656 result.m6 = vz.y; 1657 result.m7 = 0.0f; 1658 result.m8 = vx.z; 1659 result.m9 = vy.z; 1660 result.m10 = vz.z; 1661 result.m11 = 0.0f; 1662 result.m12 = -(vx.x*eye.x + vx.y*eye.y + vx.z*eye.z); // Vector3DotProduct(vx, eye) 1663 result.m13 = -(vy.x*eye.x + vy.y*eye.y + vy.z*eye.z); // Vector3DotProduct(vy, eye) 1664 result.m14 = -(vz.x*eye.x + vz.y*eye.y + vz.z*eye.z); // Vector3DotProduct(vz, eye) 1665 result.m15 = 1.0f; 1666 1667 return result; 1668 } 1669 1670 // Get float array of matrix data 1671 RMAPI float16 MatrixToFloatV(Matrix mat) 1672 { 1673 float16 result = { 0 }; 1674 1675 result.v[0] = mat.m0; 1676 result.v[1] = mat.m1; 1677 result.v[2] = mat.m2; 1678 result.v[3] = mat.m3; 1679 result.v[4] = mat.m4; 1680 result.v[5] = mat.m5; 1681 result.v[6] = mat.m6; 1682 result.v[7] = mat.m7; 1683 result.v[8] = mat.m8; 1684 result.v[9] = mat.m9; 1685 result.v[10] = mat.m10; 1686 result.v[11] = mat.m11; 1687 result.v[12] = mat.m12; 1688 result.v[13] = mat.m13; 1689 result.v[14] = mat.m14; 1690 result.v[15] = mat.m15; 1691 1692 return result; 1693 } 1694 1695 //---------------------------------------------------------------------------------- 1696 // Module Functions Definition - Quaternion math 1697 //---------------------------------------------------------------------------------- 1698 1699 // Add two quaternions 1700 RMAPI Quaternion QuaternionAdd(Quaternion q1, Quaternion q2) 1701 { 1702 Quaternion result = {q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w}; 1703 1704 return result; 1705 } 1706 1707 // Add quaternion and float value 1708 RMAPI Quaternion QuaternionAddValue(Quaternion q, float add) 1709 { 1710 Quaternion result = {q.x + add, q.y + add, q.z + add, q.w + add}; 1711 1712 return result; 1713 } 1714 1715 // Subtract two quaternions 1716 RMAPI Quaternion QuaternionSubtract(Quaternion q1, Quaternion q2) 1717 { 1718 Quaternion result = {q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w}; 1719 1720 return result; 1721 } 1722 1723 // Subtract quaternion and float value 1724 RMAPI Quaternion QuaternionSubtractValue(Quaternion q, float sub) 1725 { 1726 Quaternion result = {q.x - sub, q.y - sub, q.z - sub, q.w - sub}; 1727 1728 return result; 1729 } 1730 1731 // Get identity quaternion 1732 RMAPI Quaternion QuaternionIdentity(void) 1733 { 1734 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; 1735 1736 return result; 1737 } 1738 1739 // Computes the length of a quaternion 1740 RMAPI float QuaternionLength(Quaternion q) 1741 { 1742 float result = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 1743 1744 return result; 1745 } 1746 1747 // Normalize provided quaternion 1748 RMAPI Quaternion QuaternionNormalize(Quaternion q) 1749 { 1750 Quaternion result = { 0 }; 1751 1752 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 1753 if (length == 0.0f) length = 1.0f; 1754 float ilength = 1.0f/length; 1755 1756 result.x = q.x*ilength; 1757 result.y = q.y*ilength; 1758 result.z = q.z*ilength; 1759 result.w = q.w*ilength; 1760 1761 return result; 1762 } 1763 1764 // Invert provided quaternion 1765 RMAPI Quaternion QuaternionInvert(Quaternion q) 1766 { 1767 Quaternion result = q; 1768 1769 float lengthSq = q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w; 1770 1771 if (lengthSq != 0.0f) 1772 { 1773 float invLength = 1.0f/lengthSq; 1774 1775 result.x *= -invLength; 1776 result.y *= -invLength; 1777 result.z *= -invLength; 1778 result.w *= invLength; 1779 } 1780 1781 return result; 1782 } 1783 1784 // Calculate two quaternion multiplication 1785 RMAPI Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) 1786 { 1787 Quaternion result = { 0 }; 1788 1789 float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w; 1790 float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w; 1791 1792 result.x = qax*qbw + qaw*qbx + qay*qbz - qaz*qby; 1793 result.y = qay*qbw + qaw*qby + qaz*qbx - qax*qbz; 1794 result.z = qaz*qbw + qaw*qbz + qax*qby - qay*qbx; 1795 result.w = qaw*qbw - qax*qbx - qay*qby - qaz*qbz; 1796 1797 return result; 1798 } 1799 1800 // Scale quaternion by float value 1801 RMAPI Quaternion QuaternionScale(Quaternion q, float mul) 1802 { 1803 Quaternion result = { 0 }; 1804 1805 result.x = q.x*mul; 1806 result.y = q.y*mul; 1807 result.z = q.z*mul; 1808 result.w = q.w*mul; 1809 1810 return result; 1811 } 1812 1813 // Divide two quaternions 1814 RMAPI Quaternion QuaternionDivide(Quaternion q1, Quaternion q2) 1815 { 1816 Quaternion result = { q1.x/q2.x, q1.y/q2.y, q1.z/q2.z, q1.w/q2.w }; 1817 1818 return result; 1819 } 1820 1821 // Calculate linear interpolation between two quaternions 1822 RMAPI Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount) 1823 { 1824 Quaternion result = { 0 }; 1825 1826 result.x = q1.x + amount*(q2.x - q1.x); 1827 result.y = q1.y + amount*(q2.y - q1.y); 1828 result.z = q1.z + amount*(q2.z - q1.z); 1829 result.w = q1.w + amount*(q2.w - q1.w); 1830 1831 return result; 1832 } 1833 1834 // Calculate slerp-optimized interpolation between two quaternions 1835 RMAPI Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount) 1836 { 1837 Quaternion result = { 0 }; 1838 1839 // QuaternionLerp(q1, q2, amount) 1840 result.x = q1.x + amount*(q2.x - q1.x); 1841 result.y = q1.y + amount*(q2.y - q1.y); 1842 result.z = q1.z + amount*(q2.z - q1.z); 1843 result.w = q1.w + amount*(q2.w - q1.w); 1844 1845 // QuaternionNormalize(q); 1846 Quaternion q = result; 1847 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 1848 if (length == 0.0f) length = 1.0f; 1849 float ilength = 1.0f/length; 1850 1851 result.x = q.x*ilength; 1852 result.y = q.y*ilength; 1853 result.z = q.z*ilength; 1854 result.w = q.w*ilength; 1855 1856 return result; 1857 } 1858 1859 // Calculates spherical linear interpolation between two quaternions 1860 RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) 1861 { 1862 Quaternion result = { 0 }; 1863 1864 #if !defined(EPSILON) 1865 #define EPSILON 0.000001f 1866 #endif 1867 1868 float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w; 1869 1870 if (cosHalfTheta < 0) 1871 { 1872 q2.x = -q2.x; q2.y = -q2.y; q2.z = -q2.z; q2.w = -q2.w; 1873 cosHalfTheta = -cosHalfTheta; 1874 } 1875 1876 if (fabsf(cosHalfTheta) >= 1.0f) result = q1; 1877 else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount); 1878 else 1879 { 1880 float halfTheta = acosf(cosHalfTheta); 1881 float sinHalfTheta = sqrtf(1.0f - cosHalfTheta*cosHalfTheta); 1882 1883 if (fabsf(sinHalfTheta) < EPSILON) 1884 { 1885 result.x = (q1.x*0.5f + q2.x*0.5f); 1886 result.y = (q1.y*0.5f + q2.y*0.5f); 1887 result.z = (q1.z*0.5f + q2.z*0.5f); 1888 result.w = (q1.w*0.5f + q2.w*0.5f); 1889 } 1890 else 1891 { 1892 float ratioA = sinf((1 - amount)*halfTheta)/sinHalfTheta; 1893 float ratioB = sinf(amount*halfTheta)/sinHalfTheta; 1894 1895 result.x = (q1.x*ratioA + q2.x*ratioB); 1896 result.y = (q1.y*ratioA + q2.y*ratioB); 1897 result.z = (q1.z*ratioA + q2.z*ratioB); 1898 result.w = (q1.w*ratioA + q2.w*ratioB); 1899 } 1900 } 1901 1902 return result; 1903 } 1904 1905 // Calculate quaternion based on the rotation from one vector to another 1906 RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) 1907 { 1908 Quaternion result = { 0 }; 1909 1910 float cos2Theta = (from.x*to.x + from.y*to.y + from.z*to.z); // Vector3DotProduct(from, to) 1911 Vector3 cross = { from.y*to.z - from.z*to.y, from.z*to.x - from.x*to.z, from.x*to.y - from.y*to.x }; // Vector3CrossProduct(from, to) 1912 1913 result.x = cross.x; 1914 result.y = cross.y; 1915 result.z = cross.z; 1916 result.w = 1.0f + cos2Theta; 1917 1918 // QuaternionNormalize(q); 1919 // NOTE: Normalize to essentially nlerp the original and identity to 0.5 1920 Quaternion q = result; 1921 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 1922 if (length == 0.0f) length = 1.0f; 1923 float ilength = 1.0f/length; 1924 1925 result.x = q.x*ilength; 1926 result.y = q.y*ilength; 1927 result.z = q.z*ilength; 1928 result.w = q.w*ilength; 1929 1930 return result; 1931 } 1932 1933 // Get a quaternion for a given rotation matrix 1934 RMAPI Quaternion QuaternionFromMatrix(Matrix mat) 1935 { 1936 Quaternion result = { 0 }; 1937 1938 float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10; 1939 float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10; 1940 float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10; 1941 float fourZSquaredMinus1 = mat.m10 - mat.m0 - mat.m5; 1942 1943 int biggestIndex = 0; 1944 float fourBiggestSquaredMinus1 = fourWSquaredMinus1; 1945 if (fourXSquaredMinus1 > fourBiggestSquaredMinus1) 1946 { 1947 fourBiggestSquaredMinus1 = fourXSquaredMinus1; 1948 biggestIndex = 1; 1949 } 1950 1951 if (fourYSquaredMinus1 > fourBiggestSquaredMinus1) 1952 { 1953 fourBiggestSquaredMinus1 = fourYSquaredMinus1; 1954 biggestIndex = 2; 1955 } 1956 1957 if (fourZSquaredMinus1 > fourBiggestSquaredMinus1) 1958 { 1959 fourBiggestSquaredMinus1 = fourZSquaredMinus1; 1960 biggestIndex = 3; 1961 } 1962 1963 float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f)*0.5f; 1964 float mult = 0.25f/biggestVal; 1965 1966 switch (biggestIndex) 1967 { 1968 case 0: 1969 result.w = biggestVal; 1970 result.x = (mat.m6 - mat.m9)*mult; 1971 result.y = (mat.m8 - mat.m2)*mult; 1972 result.z = (mat.m1 - mat.m4)*mult; 1973 break; 1974 case 1: 1975 result.x = biggestVal; 1976 result.w = (mat.m6 - mat.m9)*mult; 1977 result.y = (mat.m1 + mat.m4)*mult; 1978 result.z = (mat.m8 + mat.m2)*mult; 1979 break; 1980 case 2: 1981 result.y = biggestVal; 1982 result.w = (mat.m8 - mat.m2)*mult; 1983 result.x = (mat.m1 + mat.m4)*mult; 1984 result.z = (mat.m6 + mat.m9)*mult; 1985 break; 1986 case 3: 1987 result.z = biggestVal; 1988 result.w = (mat.m1 - mat.m4)*mult; 1989 result.x = (mat.m8 + mat.m2)*mult; 1990 result.y = (mat.m6 + mat.m9)*mult; 1991 break; 1992 } 1993 1994 return result; 1995 } 1996 1997 // Get a matrix for a given quaternion 1998 RMAPI Matrix QuaternionToMatrix(Quaternion q) 1999 { 2000 Matrix result = { 1.0f, 0.0f, 0.0f, 0.0f, 2001 0.0f, 1.0f, 0.0f, 0.0f, 2002 0.0f, 0.0f, 1.0f, 0.0f, 2003 0.0f, 0.0f, 0.0f, 1.0f }; // MatrixIdentity() 2004 2005 float a2 = q.x*q.x; 2006 float b2 = q.y*q.y; 2007 float c2 = q.z*q.z; 2008 float ac = q.x*q.z; 2009 float ab = q.x*q.y; 2010 float bc = q.y*q.z; 2011 float ad = q.w*q.x; 2012 float bd = q.w*q.y; 2013 float cd = q.w*q.z; 2014 2015 result.m0 = 1 - 2*(b2 + c2); 2016 result.m1 = 2*(ab + cd); 2017 result.m2 = 2*(ac - bd); 2018 2019 result.m4 = 2*(ab - cd); 2020 result.m5 = 1 - 2*(a2 + c2); 2021 result.m6 = 2*(bc + ad); 2022 2023 result.m8 = 2*(ac + bd); 2024 result.m9 = 2*(bc - ad); 2025 result.m10 = 1 - 2*(a2 + b2); 2026 2027 return result; 2028 } 2029 2030 // Get rotation quaternion for an angle and axis 2031 // NOTE: Angle must be provided in radians 2032 RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) 2033 { 2034 Quaternion result = { 0.0f, 0.0f, 0.0f, 1.0f }; 2035 2036 float axisLength = sqrtf(axis.x*axis.x + axis.y*axis.y + axis.z*axis.z); 2037 2038 if (axisLength != 0.0f) 2039 { 2040 angle *= 0.5f; 2041 2042 float length = 0.0f; 2043 float ilength = 0.0f; 2044 2045 // Vector3Normalize(axis) 2046 Vector3 v = axis; 2047 length = sqrtf(v.x*v.x + v.y*v.y + v.z*v.z); 2048 if (length == 0.0f) length = 1.0f; 2049 ilength = 1.0f/length; 2050 axis.x *= ilength; 2051 axis.y *= ilength; 2052 axis.z *= ilength; 2053 2054 float sinres = sinf(angle); 2055 float cosres = cosf(angle); 2056 2057 result.x = axis.x*sinres; 2058 result.y = axis.y*sinres; 2059 result.z = axis.z*sinres; 2060 result.w = cosres; 2061 2062 // QuaternionNormalize(q); 2063 Quaternion q = result; 2064 length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 2065 if (length == 0.0f) length = 1.0f; 2066 ilength = 1.0f/length; 2067 result.x = q.x*ilength; 2068 result.y = q.y*ilength; 2069 result.z = q.z*ilength; 2070 result.w = q.w*ilength; 2071 } 2072 2073 return result; 2074 } 2075 2076 // Get the rotation angle and axis for a given quaternion 2077 RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle) 2078 { 2079 if (fabsf(q.w) > 1.0f) 2080 { 2081 // QuaternionNormalize(q); 2082 float length = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); 2083 if (length == 0.0f) length = 1.0f; 2084 float ilength = 1.0f/length; 2085 2086 q.x = q.x*ilength; 2087 q.y = q.y*ilength; 2088 q.z = q.z*ilength; 2089 q.w = q.w*ilength; 2090 } 2091 2092 Vector3 resAxis = { 0.0f, 0.0f, 0.0f }; 2093 float resAngle = 2.0f*acosf(q.w); 2094 float den = sqrtf(1.0f - q.w*q.w); 2095 2096 if (den > EPSILON) 2097 { 2098 resAxis.x = q.x/den; 2099 resAxis.y = q.y/den; 2100 resAxis.z = q.z/den; 2101 } 2102 else 2103 { 2104 // This occurs when the angle is zero. 2105 // Not a problem: just set an arbitrary normalized axis. 2106 resAxis.x = 1.0f; 2107 } 2108 2109 *outAxis = resAxis; 2110 *outAngle = resAngle; 2111 } 2112 2113 // Get the quaternion equivalent to Euler angles 2114 // NOTE: Rotation order is ZYX 2115 RMAPI Quaternion QuaternionFromEuler(float pitch, float yaw, float roll) 2116 { 2117 Quaternion result = { 0 }; 2118 2119 float x0 = cosf(pitch*0.5f); 2120 float x1 = sinf(pitch*0.5f); 2121 float y0 = cosf(yaw*0.5f); 2122 float y1 = sinf(yaw*0.5f); 2123 float z0 = cosf(roll*0.5f); 2124 float z1 = sinf(roll*0.5f); 2125 2126 result.x = x1*y0*z0 - x0*y1*z1; 2127 result.y = x0*y1*z0 + x1*y0*z1; 2128 result.z = x0*y0*z1 - x1*y1*z0; 2129 result.w = x0*y0*z0 + x1*y1*z1; 2130 2131 return result; 2132 } 2133 2134 // Get the Euler angles equivalent to quaternion (roll, pitch, yaw) 2135 // NOTE: Angles are returned in a Vector3 struct in radians 2136 RMAPI Vector3 QuaternionToEuler(Quaternion q) 2137 { 2138 Vector3 result = { 0 }; 2139 2140 // Roll (x-axis rotation) 2141 float x0 = 2.0f*(q.w*q.x + q.y*q.z); 2142 float x1 = 1.0f - 2.0f*(q.x*q.x + q.y*q.y); 2143 result.x = atan2f(x0, x1); 2144 2145 // Pitch (y-axis rotation) 2146 float y0 = 2.0f*(q.w*q.y - q.z*q.x); 2147 y0 = y0 > 1.0f ? 1.0f : y0; 2148 y0 = y0 < -1.0f ? -1.0f : y0; 2149 result.y = asinf(y0); 2150 2151 // Yaw (z-axis rotation) 2152 float z0 = 2.0f*(q.w*q.z + q.x*q.y); 2153 float z1 = 1.0f - 2.0f*(q.y*q.y + q.z*q.z); 2154 result.z = atan2f(z0, z1); 2155 2156 return result; 2157 } 2158 2159 // Transform a quaternion given a transformation matrix 2160 RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat) 2161 { 2162 Quaternion result = { 0 }; 2163 2164 result.x = mat.m0*q.x + mat.m4*q.y + mat.m8*q.z + mat.m12*q.w; 2165 result.y = mat.m1*q.x + mat.m5*q.y + mat.m9*q.z + mat.m13*q.w; 2166 result.z = mat.m2*q.x + mat.m6*q.y + mat.m10*q.z + mat.m14*q.w; 2167 result.w = mat.m3*q.x + mat.m7*q.y + mat.m11*q.z + mat.m15*q.w; 2168 2169 return result; 2170 } 2171 2172 // Check whether two given quaternions are almost equal 2173 RMAPI int QuaternionEquals(Quaternion p, Quaternion q) 2174 { 2175 #if !defined(EPSILON) 2176 #define EPSILON 0.000001f 2177 #endif 2178 2179 int result = (((fabsf(p.x - q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 2180 ((fabsf(p.y - q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && 2181 ((fabsf(p.z - q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && 2182 ((fabsf(p.w - q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))) || 2183 (((fabsf(p.x + q.x)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 2184 ((fabsf(p.y + q.y)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && 2185 ((fabsf(p.z + q.z)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && 2186 ((fabsf(p.w + q.w)) <= (EPSILON*fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))); 2187 2188 return result; 2189 } 2190 2191 #endif // RAYMATH_H