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 114typedef 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 123typedef 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 133typedef 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 144typedef 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) 150typedef 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 160typedef struct float3 { 161 float v[3]; 162} float3; 163 164typedef 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 175RMAPI 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 185RMAPI 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 193RMAPI 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 201RMAPI 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 209RMAPI 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 217RMAPI 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 233RMAPI Vector2 Vector2Zero(void) 234{ 235 Vector2 result = { 0.0f, 0.0f }; 236 237 return result; 238} 239 240// Vector with components value 1.0f 241RMAPI Vector2 Vector2One(void) 242{ 243 Vector2 result = { 1.0f, 1.0f }; 244 245 return result; 246} 247 248// Add two vectors (v1 + v2) 249RMAPI 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 257RMAPI 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) 265RMAPI 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 273RMAPI 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 281RMAPI 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 289RMAPI 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 297RMAPI 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 305RMAPI 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 313RMAPI 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) 322RMAPI 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 337RMAPI 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) 348RMAPI 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 356RMAPI 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 364RMAPI Vector2 Vector2Negate(Vector2 v) 365{ 366 Vector2 result = { -v.x, -v.y }; 367 368 return result; 369} 370 371// Divide vector by vector 372RMAPI 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 380RMAPI 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 396RMAPI 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 411RMAPI 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 422RMAPI 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 435RMAPI 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 449RMAPI 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 468RMAPI 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 477RMAPI 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 488RMAPI 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 515RMAPI 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 532RMAPI 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 540RMAPI Vector3 Vector3One(void) 541{ 542 Vector3 result = { 1.0f, 1.0f, 1.0f }; 543 544 return result; 545} 546 547// Add two vectors 548RMAPI 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 556RMAPI 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 564RMAPI 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 572RMAPI 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 580RMAPI 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 588RMAPI 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 596RMAPI 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 604RMAPI 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 633RMAPI 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 641RMAPI 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 649RMAPI 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 657RMAPI 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 670RMAPI 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 683RMAPI 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) 696RMAPI 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 704RMAPI 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 712RMAPI 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 730RMAPI 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 747RMAPI 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 766RMAPI 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 799RMAPI 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 815RMAPI 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 827RMAPI 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 879RMAPI 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 891RMAPI 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 909RMAPI 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 921RMAPI 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 934RMAPI 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 958RMAPI 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 1041RMAPI 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 1053RMAPI 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 1062RMAPI 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 1074RMAPI 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 1102RMAPI 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 1120RMAPI 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 1145RMAPI 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) 1166RMAPI 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 1174RMAPI 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 1199RMAPI 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 1246RMAPI 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 1257RMAPI 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) 1282RMAPI 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! 1308RMAPI 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 1333RMAPI 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 1345RMAPI 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 1390RMAPI 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 1410RMAPI 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 1430RMAPI 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 1451RMAPI 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 1482RMAPI 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 1517RMAPI 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 1528RMAPI 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 1561RMAPI 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 1587RMAPI 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) 1616RMAPI 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 1671RMAPI 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 1700RMAPI 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 1708RMAPI 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 1716RMAPI 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 1724RMAPI 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 1732RMAPI 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 1740RMAPI 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 1748RMAPI 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 1765RMAPI 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 1785RMAPI 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 1801RMAPI 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 1814RMAPI 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 1822RMAPI 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 1835RMAPI 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 1860RMAPI 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 1906RMAPI 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 1934RMAPI 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 1998RMAPI 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 2032RMAPI 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 2077RMAPI 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 2115RMAPI 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 2136RMAPI 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 2160RMAPI 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 2173RMAPI 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