A RPG I'm messing with made in Raylib.
at main 86 kB view raw
1/********************************************************************************************** 2 * 3 * raymath v2.0 - Math functions to work with Vector2, Vector3, Matrix and 4 * Quaternions 5 * 6 * CONVENTIONS: 7 * - Matrix structure is defined as row-major (memory layout) but parameters 8 * naming AND all math operations performed by the library consider the 9 * structure as it was column-major It is like transposed versions of the 10 * matrices are used for all the maths It benefits some functions making them 11 * cache-friendly and also avoids matrix transpositions sometimes required by 12 * OpenGL Example: In memory order, row0 is [m0 m4 m8 m12] but in semantic math 13 * row0 is [m0 m1 m2 m3] 14 * - Functions are always self-contained, no function use another raymath 15 * function inside, required code is directly re-implemented inside 16 * - Functions input parameters are always received by value (2 unavoidable 17 * exceptions) 18 * - Functions use always a "result" variable for return (except C++ 19 * operators) 20 * - Functions are always defined inline 21 * - Angles are always in radians (DEG2RAD/RAD2DEG macros provided for 22 * convenience) 23 * - No compound literals used to make sure libray is compatible with C++ 24 * 25 * CONFIGURATION: 26 * #define RAYMATH_IMPLEMENTATION 27 * Generates the implementation of the library into the included file. 28 * If not defined, the library is in header only mode and can be 29 * included in other headers or source files without problems. But only ONE file 30 * should hold the implementation. 31 * 32 * #define RAYMATH_STATIC_INLINE 33 * Define static inline functions code, so #include header suffices 34 * for use. This may use up lots of memory. 35 * 36 * #define RAYMATH_DISABLE_CPP_OPERATORS 37 * Disables C++ operator overloads for raymath types. 38 * 39 * LICENSE: zlib/libpng 40 * 41 * Copyright (c) 2015-2025 Ramon Santamaria (@raysan5) 42 * 43 * This software is provided "as-is", without any express or implied warranty. 44 * In no event will the authors be held liable for any damages arising from the 45 * use of this software. 46 * 47 * Permission is granted to anyone to use this software for any purpose, 48 * including commercial applications, and to alter it and redistribute it 49 * freely, subject to the following restrictions: 50 * 51 * 1. The origin of this software must not be misrepresented; you must not 52 * claim that you wrote the original software. If you use this software in a 53 * product, an acknowledgment in the product documentation would be appreciated 54 * but is not required. 55 * 56 * 2. Altered source versions must be plainly marked as such, and must not 57 * be misrepresented as being the original software. 58 * 59 * 3. This notice may not be removed or altered from any source 60 * distribution. 61 * 62 **********************************************************************************************/ 63 64#ifndef RAYMATH_H 65#define RAYMATH_H 66 67#if defined(RAYMATH_IMPLEMENTATION) && defined(RAYMATH_STATIC_INLINE) 68#error \ 69 "Specifying both RAYMATH_IMPLEMENTATION and RAYMATH_STATIC_INLINE is contradictory" 70#endif 71 72// Function specifiers definition 73#if defined(RAYMATH_IMPLEMENTATION) 74#if defined(_WIN32) && defined(BUILD_LIBTYPE_SHARED) 75#define RMAPI \ 76 __declspec(dllexport) extern inline // We are building raylib as a Win32 77 // shared library (.dll) 78#elif defined(BUILD_LIBTYPE_SHARED) 79#define RMAPI \ 80 __attribute__((visibility("default"))) // We are building raylib as a Unix 81 // shared library (.so/.dylib) 82#elif defined(_WIN32) && defined(USE_LIBTYPE_SHARED) 83#define RMAPI \ 84 __declspec(dllimport) // We are using raylib as a Win32 shared library (.dll) 85#else 86#define RMAPI extern inline // Provide external definition 87#endif 88#elif defined(RAYMATH_STATIC_INLINE) 89#define RMAPI \ 90 static inline // Functions may be inlined, no external out-of-line definition 91#else 92#if defined(__TINYC__) 93#define RMAPI \ 94 static inline // plain inline not supported by tinycc (See issue #435) 95#else 96#define RMAPI inline // Functions may be inlined or external definition used 97#endif 98#endif 99 100//---------------------------------------------------------------------------------- 101// Defines and Macros 102//---------------------------------------------------------------------------------- 103#ifndef PI 104#define PI 3.14159265358979323846f 105#endif 106 107#ifndef EPSILON 108#define EPSILON 0.000001f 109#endif 110 111#ifndef DEG2RAD 112#define DEG2RAD (PI / 180.0f) 113#endif 114 115#ifndef RAD2DEG 116#define RAD2DEG (180.0f / PI) 117#endif 118 119// Get float vector for Matrix 120#ifndef MatrixToFloat 121#define MatrixToFloat(mat) (MatrixToFloatV(mat).v) 122#endif 123 124// Get float vector for Vector3 125#ifndef Vector3ToFloat 126#define Vector3ToFloat(vec) (Vector3ToFloatV(vec).v) 127#endif 128 129//---------------------------------------------------------------------------------- 130// Types and Structures Definition 131//---------------------------------------------------------------------------------- 132#if !defined(RL_VECTOR2_TYPE) 133// Vector2 type 134typedef struct Vector2 { 135 float x; 136 float y; 137} Vector2; 138#define RL_VECTOR2_TYPE 139#endif 140 141#if !defined(RL_VECTOR3_TYPE) 142// Vector3 type 143typedef struct Vector3 { 144 float x; 145 float y; 146 float z; 147} Vector3; 148#define RL_VECTOR3_TYPE 149#endif 150 151#if !defined(RL_VECTOR4_TYPE) 152// Vector4 type 153typedef struct Vector4 { 154 float x; 155 float y; 156 float z; 157 float w; 158} Vector4; 159#define RL_VECTOR4_TYPE 160#endif 161 162#if !defined(RL_QUATERNION_TYPE) 163// Quaternion type 164typedef Vector4 Quaternion; 165#define RL_QUATERNION_TYPE 166#endif 167 168#if !defined(RL_MATRIX_TYPE) 169// Matrix type (OpenGL style 4x4 - right handed, column major) 170typedef struct Matrix { 171 float m0, m4, m8, m12; // Matrix first row (4 components) 172 float m1, m5, m9, m13; // Matrix second row (4 components) 173 float m2, m6, m10, m14; // Matrix third row (4 components) 174 float m3, m7, m11, m15; // Matrix fourth row (4 components) 175} Matrix; 176#define RL_MATRIX_TYPE 177#endif 178 179// NOTE: Helper types to be used instead of array return types for *ToFloat 180// functions 181typedef struct float3 { 182 float v[3]; 183} float3; 184 185typedef struct float16 { 186 float v[16]; 187} float16; 188 189#include <math.h> // Required for: sinf(), cosf(), tan(), atan2f(), sqrtf(), floor(), fminf(), fmaxf(), fabsf() 190 191//---------------------------------------------------------------------------------- 192// Module Functions Definition - Utils math 193//---------------------------------------------------------------------------------- 194 195// Clamp float value 196RMAPI float Clamp(float value, float min, float max) { 197 float result = (value < min) ? min : value; 198 199 if (result > max) 200 result = max; 201 202 return result; 203} 204 205// Calculate linear interpolation between two floats 206RMAPI float Lerp(float start, float end, float amount) { 207 float result = start + amount * (end - start); 208 209 return result; 210} 211 212// Normalize input value within input range 213RMAPI float Normalize(float value, float start, float end) { 214 float result = (value - start) / (end - start); 215 216 return result; 217} 218 219// Remap input value within input range to output range 220RMAPI float Remap(float value, float inputStart, float inputEnd, 221 float outputStart, float outputEnd) { 222 float result = (value - inputStart) / (inputEnd - inputStart) * 223 (outputEnd - outputStart) + 224 outputStart; 225 226 return result; 227} 228 229// Wrap input value from min to max 230RMAPI float Wrap(float value, float min, float max) { 231 float result = value - (max - min) * floorf((value - min) / (max - min)); 232 233 return result; 234} 235 236// Check whether two given floats are almost equal 237RMAPI int FloatEquals(float x, float y) { 238#if !defined(EPSILON) 239#define EPSILON 0.000001f 240#endif 241 242 int result = 243 (fabsf(x - y)) <= (EPSILON * fmaxf(1.0f, fmaxf(fabsf(x), fabsf(y)))); 244 245 return result; 246} 247 248//---------------------------------------------------------------------------------- 249// Module Functions Definition - Vector2 math 250//---------------------------------------------------------------------------------- 251 252// Vector with components value 0.0f 253RMAPI Vector2 Vector2Zero(void) { 254 Vector2 result = {0.0f, 0.0f}; 255 256 return result; 257} 258 259// Vector with components value 1.0f 260RMAPI Vector2 Vector2One(void) { 261 Vector2 result = {1.0f, 1.0f}; 262 263 return result; 264} 265 266// Add two vectors (v1 + v2) 267RMAPI Vector2 Vector2Add(Vector2 v1, Vector2 v2) { 268 Vector2 result = {v1.x + v2.x, v1.y + v2.y}; 269 270 return result; 271} 272 273// Add vector and float value 274RMAPI Vector2 Vector2AddValue(Vector2 v, float add) { 275 Vector2 result = {v.x + add, v.y + add}; 276 277 return result; 278} 279 280// Subtract two vectors (v1 - v2) 281RMAPI Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) { 282 Vector2 result = {v1.x - v2.x, v1.y - v2.y}; 283 284 return result; 285} 286 287// Subtract vector by float value 288RMAPI Vector2 Vector2SubtractValue(Vector2 v, float sub) { 289 Vector2 result = {v.x - sub, v.y - sub}; 290 291 return result; 292} 293 294// Calculate vector length 295RMAPI float Vector2Length(Vector2 v) { 296 float result = sqrtf((v.x * v.x) + (v.y * v.y)); 297 298 return result; 299} 300 301// Calculate vector square length 302RMAPI float Vector2LengthSqr(Vector2 v) { 303 float result = (v.x * v.x) + (v.y * v.y); 304 305 return result; 306} 307 308// Calculate two vectors dot product 309RMAPI float Vector2DotProduct(Vector2 v1, Vector2 v2) { 310 float result = (v1.x * v2.x + v1.y * v2.y); 311 312 return result; 313} 314 315// Calculate two vectors cross product 316RMAPI float Vector2CrossProduct(Vector2 v1, Vector2 v2) { 317 float result = (v1.x * v2.y - v1.y * v2.x); 318 319 return result; 320} 321 322// Calculate distance between two vectors 323RMAPI float Vector2Distance(Vector2 v1, Vector2 v2) { 324 float result = 325 sqrtf((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y)); 326 327 return result; 328} 329 330// Calculate square distance between two vectors 331RMAPI float Vector2DistanceSqr(Vector2 v1, Vector2 v2) { 332 float result = 333 ((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y)); 334 335 return result; 336} 337 338// Calculate the signed angle from v1 to v2, relative to the origin (0, 0) 339// NOTE: Coordinate system convention: positive X right, positive Y down 340// positive angles appear clockwise, and negative angles appear counterclockwise 341RMAPI float Vector2Angle(Vector2 v1, Vector2 v2) { 342 float result = 0.0f; 343 344 float dot = v1.x * v2.x + v1.y * v2.y; 345 float det = v1.x * v2.y - v1.y * v2.x; 346 347 result = atan2f(det, dot); 348 349 return result; 350} 351 352// Calculate angle defined by a two vectors line 353// NOTE: Parameters need to be normalized 354// Current implementation should be aligned with glm::angle 355RMAPI float Vector2LineAngle(Vector2 start, Vector2 end) { 356 float result = 0.0f; 357 358 // TODO(10/9/2023): Currently angles move clockwise, determine if this is 359 // wanted behavior 360 result = -atan2f(end.y - start.y, end.x - start.x); 361 362 return result; 363} 364 365// Scale vector (multiply by value) 366RMAPI Vector2 Vector2Scale(Vector2 v, float scale) { 367 Vector2 result = {v.x * scale, v.y * scale}; 368 369 return result; 370} 371 372// Multiply vector by vector 373RMAPI Vector2 Vector2Multiply(Vector2 v1, Vector2 v2) { 374 Vector2 result = {v1.x * v2.x, v1.y * v2.y}; 375 376 return result; 377} 378 379// Negate vector 380RMAPI Vector2 Vector2Negate(Vector2 v) { 381 Vector2 result = {-v.x, -v.y}; 382 383 return result; 384} 385 386// Divide vector by vector 387RMAPI Vector2 Vector2Divide(Vector2 v1, Vector2 v2) { 388 Vector2 result = {v1.x / v2.x, v1.y / v2.y}; 389 390 return result; 391} 392 393// Normalize provided vector 394RMAPI Vector2 Vector2Normalize(Vector2 v) { 395 Vector2 result = {0}; 396 float length = sqrtf((v.x * v.x) + (v.y * v.y)); 397 398 if (length > 0) { 399 float ilength = 1.0f / length; 400 result.x = v.x * ilength; 401 result.y = v.y * ilength; 402 } 403 404 return result; 405} 406 407// Transforms a Vector2 by a given Matrix 408RMAPI Vector2 Vector2Transform(Vector2 v, Matrix mat) { 409 Vector2 result = {0}; 410 411 float x = v.x; 412 float y = v.y; 413 float z = 0; 414 415 result.x = mat.m0 * x + mat.m4 * y + mat.m8 * z + mat.m12; 416 result.y = mat.m1 * x + mat.m5 * y + mat.m9 * z + mat.m13; 417 418 return result; 419} 420 421// Calculate linear interpolation between two vectors 422RMAPI Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount) { 423 Vector2 result = {0}; 424 425 result.x = v1.x + amount * (v2.x - v1.x); 426 result.y = v1.y + amount * (v2.y - v1.y); 427 428 return result; 429} 430 431// Calculate reflected vector to normal 432RMAPI Vector2 Vector2Reflect(Vector2 v, Vector2 normal) { 433 Vector2 result = {0}; 434 435 float dotProduct = (v.x * normal.x + v.y * normal.y); // Dot product 436 437 result.x = v.x - (2.0f * normal.x) * dotProduct; 438 result.y = v.y - (2.0f * normal.y) * dotProduct; 439 440 return result; 441} 442 443// Get min value for each pair of components 444RMAPI Vector2 Vector2Min(Vector2 v1, Vector2 v2) { 445 Vector2 result = {0}; 446 447 result.x = fminf(v1.x, v2.x); 448 result.y = fminf(v1.y, v2.y); 449 450 return result; 451} 452 453// Get max value for each pair of components 454RMAPI Vector2 Vector2Max(Vector2 v1, Vector2 v2) { 455 Vector2 result = {0}; 456 457 result.x = fmaxf(v1.x, v2.x); 458 result.y = fmaxf(v1.y, v2.y); 459 460 return result; 461} 462 463// Rotate vector by angle 464RMAPI Vector2 Vector2Rotate(Vector2 v, float angle) { 465 Vector2 result = {0}; 466 467 float cosres = cosf(angle); 468 float sinres = sinf(angle); 469 470 result.x = v.x * cosres - v.y * sinres; 471 result.y = v.x * sinres + v.y * cosres; 472 473 return result; 474} 475 476// Move Vector towards target 477RMAPI Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance) { 478 Vector2 result = {0}; 479 480 float dx = target.x - v.x; 481 float dy = target.y - v.y; 482 float value = (dx * dx) + (dy * dy); 483 484 if ((value == 0) || 485 ((maxDistance >= 0) && (value <= maxDistance * maxDistance))) 486 return target; 487 488 float dist = sqrtf(value); 489 490 result.x = v.x + dx / dist * maxDistance; 491 result.y = v.y + dy / dist * maxDistance; 492 493 return result; 494} 495 496// Invert the given vector 497RMAPI Vector2 Vector2Invert(Vector2 v) { 498 Vector2 result = {1.0f / v.x, 1.0f / v.y}; 499 500 return result; 501} 502 503// Clamp the components of the vector between 504// min and max values specified by the given vectors 505RMAPI Vector2 Vector2Clamp(Vector2 v, Vector2 min, Vector2 max) { 506 Vector2 result = {0}; 507 508 result.x = fminf(max.x, fmaxf(min.x, v.x)); 509 result.y = fminf(max.y, fmaxf(min.y, v.y)); 510 511 return result; 512} 513 514// Clamp the magnitude of the vector between two min and max values 515RMAPI Vector2 Vector2ClampValue(Vector2 v, float min, float max) { 516 Vector2 result = v; 517 518 float length = (v.x * v.x) + (v.y * v.y); 519 if (length > 0.0f) { 520 length = sqrtf(length); 521 522 float scale = 1; // By default, 1 as the neutral element. 523 if (length < min) { 524 scale = min / length; 525 } else if (length > max) { 526 scale = max / length; 527 } 528 529 result.x = v.x * scale; 530 result.y = v.y * scale; 531 } 532 533 return result; 534} 535 536// Check whether two given vectors are almost equal 537RMAPI int Vector2Equals(Vector2 p, Vector2 q) { 538#if !defined(EPSILON) 539#define EPSILON 0.000001f 540#endif 541 542 int result = ((fabsf(p.x - q.x)) <= 543 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 544 ((fabsf(p.y - q.y)) <= 545 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))); 546 547 return result; 548} 549 550// Compute the direction of a refracted ray 551// v: normalized direction of the incoming ray 552// n: normalized normal vector of the interface of two optical media 553// r: ratio of the refractive index of the medium from where the ray comes 554// to the refractive index of the medium on the other side of the surface 555RMAPI Vector2 Vector2Refract(Vector2 v, Vector2 n, float r) { 556 Vector2 result = {0}; 557 558 float dot = v.x * n.x + v.y * n.y; 559 float d = 1.0f - r * r * (1.0f - dot * dot); 560 561 if (d >= 0.0f) { 562 d = sqrtf(d); 563 v.x = r * v.x - (r * dot + d) * n.x; 564 v.y = r * v.y - (r * dot + d) * n.y; 565 566 result = v; 567 } 568 569 return result; 570} 571 572//---------------------------------------------------------------------------------- 573// Module Functions Definition - Vector3 math 574//---------------------------------------------------------------------------------- 575 576// Vector with components value 0.0f 577RMAPI Vector3 Vector3Zero(void) { 578 Vector3 result = {0.0f, 0.0f, 0.0f}; 579 580 return result; 581} 582 583// Vector with components value 1.0f 584RMAPI Vector3 Vector3One(void) { 585 Vector3 result = {1.0f, 1.0f, 1.0f}; 586 587 return result; 588} 589 590// Add two vectors 591RMAPI Vector3 Vector3Add(Vector3 v1, Vector3 v2) { 592 Vector3 result = {v1.x + v2.x, v1.y + v2.y, v1.z + v2.z}; 593 594 return result; 595} 596 597// Add vector and float value 598RMAPI Vector3 Vector3AddValue(Vector3 v, float add) { 599 Vector3 result = {v.x + add, v.y + add, v.z + add}; 600 601 return result; 602} 603 604// Subtract two vectors 605RMAPI Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) { 606 Vector3 result = {v1.x - v2.x, v1.y - v2.y, v1.z - v2.z}; 607 608 return result; 609} 610 611// Subtract vector by float value 612RMAPI Vector3 Vector3SubtractValue(Vector3 v, float sub) { 613 Vector3 result = {v.x - sub, v.y - sub, v.z - sub}; 614 615 return result; 616} 617 618// Multiply vector by scalar 619RMAPI Vector3 Vector3Scale(Vector3 v, float scalar) { 620 Vector3 result = {v.x * scalar, v.y * scalar, v.z * scalar}; 621 622 return result; 623} 624 625// Multiply vector by vector 626RMAPI Vector3 Vector3Multiply(Vector3 v1, Vector3 v2) { 627 Vector3 result = {v1.x * v2.x, v1.y * v2.y, v1.z * v2.z}; 628 629 return result; 630} 631 632// Calculate two vectors cross product 633RMAPI Vector3 Vector3CrossProduct(Vector3 v1, Vector3 v2) { 634 Vector3 result = {v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, 635 v1.x * v2.y - v1.y * v2.x}; 636 637 return result; 638} 639 640// Calculate one vector perpendicular vector 641RMAPI Vector3 Vector3Perpendicular(Vector3 v) { 642 Vector3 result = {0}; 643 644 float min = fabsf(v.x); 645 Vector3 cardinalAxis = {1.0f, 0.0f, 0.0f}; 646 647 if (fabsf(v.y) < min) { 648 min = fabsf(v.y); 649 Vector3 tmp = {0.0f, 1.0f, 0.0f}; 650 cardinalAxis = tmp; 651 } 652 653 if (fabsf(v.z) < min) { 654 Vector3 tmp = {0.0f, 0.0f, 1.0f}; 655 cardinalAxis = tmp; 656 } 657 658 // Cross product between vectors 659 result.x = v.y * cardinalAxis.z - v.z * cardinalAxis.y; 660 result.y = v.z * cardinalAxis.x - v.x * cardinalAxis.z; 661 result.z = v.x * cardinalAxis.y - v.y * cardinalAxis.x; 662 663 return result; 664} 665 666// Calculate vector length 667RMAPI float Vector3Length(const Vector3 v) { 668 float result = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); 669 670 return result; 671} 672 673// Calculate vector square length 674RMAPI float Vector3LengthSqr(const Vector3 v) { 675 float result = v.x * v.x + v.y * v.y + v.z * v.z; 676 677 return result; 678} 679 680// Calculate two vectors dot product 681RMAPI float Vector3DotProduct(Vector3 v1, Vector3 v2) { 682 float result = (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z); 683 684 return result; 685} 686 687// Calculate distance between two vectors 688RMAPI float Vector3Distance(Vector3 v1, Vector3 v2) { 689 float result = 0.0f; 690 691 float dx = v2.x - v1.x; 692 float dy = v2.y - v1.y; 693 float dz = v2.z - v1.z; 694 result = sqrtf(dx * dx + dy * dy + dz * dz); 695 696 return result; 697} 698 699// Calculate square distance between two vectors 700RMAPI float Vector3DistanceSqr(Vector3 v1, Vector3 v2) { 701 float result = 0.0f; 702 703 float dx = v2.x - v1.x; 704 float dy = v2.y - v1.y; 705 float dz = v2.z - v1.z; 706 result = dx * dx + dy * dy + dz * dz; 707 708 return result; 709} 710 711// Calculate angle between two vectors 712RMAPI float Vector3Angle(Vector3 v1, Vector3 v2) { 713 float result = 0.0f; 714 715 Vector3 cross = {v1.y * v2.z - v1.z * v2.y, v1.z * v2.x - v1.x * v2.z, 716 v1.x * v2.y - v1.y * v2.x}; 717 float len = sqrtf(cross.x * cross.x + cross.y * cross.y + cross.z * cross.z); 718 float dot = (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z); 719 result = atan2f(len, dot); 720 721 return result; 722} 723 724// Negate provided vector (invert direction) 725RMAPI Vector3 Vector3Negate(Vector3 v) { 726 Vector3 result = {-v.x, -v.y, -v.z}; 727 728 return result; 729} 730 731// Divide vector by vector 732RMAPI Vector3 Vector3Divide(Vector3 v1, Vector3 v2) { 733 Vector3 result = {v1.x / v2.x, v1.y / v2.y, v1.z / v2.z}; 734 735 return result; 736} 737 738// Normalize provided vector 739RMAPI Vector3 Vector3Normalize(Vector3 v) { 740 Vector3 result = v; 741 742 float length = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); 743 if (length != 0.0f) { 744 float ilength = 1.0f / length; 745 746 result.x *= ilength; 747 result.y *= ilength; 748 result.z *= ilength; 749 } 750 751 return result; 752} 753 754// Calculate the projection of the vector v1 on to v2 755RMAPI Vector3 Vector3Project(Vector3 v1, Vector3 v2) { 756 Vector3 result = {0}; 757 758 float v1dv2 = (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z); 759 float v2dv2 = (v2.x * v2.x + v2.y * v2.y + v2.z * v2.z); 760 761 float mag = v1dv2 / v2dv2; 762 763 result.x = v2.x * mag; 764 result.y = v2.y * mag; 765 result.z = v2.z * mag; 766 767 return result; 768} 769 770// Calculate the rejection of the vector v1 on to v2 771RMAPI Vector3 Vector3Reject(Vector3 v1, Vector3 v2) { 772 Vector3 result = {0}; 773 774 float v1dv2 = (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z); 775 float v2dv2 = (v2.x * v2.x + v2.y * v2.y + v2.z * v2.z); 776 777 float mag = v1dv2 / v2dv2; 778 779 result.x = v1.x - (v2.x * mag); 780 result.y = v1.y - (v2.y * mag); 781 result.z = v1.z - (v2.z * mag); 782 783 return result; 784} 785 786// Orthonormalize provided vectors 787// Makes vectors normalized and orthogonal to each other 788// Gram-Schmidt function implementation 789RMAPI void Vector3OrthoNormalize(Vector3 *v1, Vector3 *v2) { 790 float length = 0.0f; 791 float ilength = 0.0f; 792 793 // Vector3Normalize(*v1); 794 Vector3 v = *v1; 795 length = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); 796 if (length == 0.0f) 797 length = 1.0f; 798 ilength = 1.0f / length; 799 v1->x *= ilength; 800 v1->y *= ilength; 801 v1->z *= ilength; 802 803 // Vector3CrossProduct(*v1, *v2) 804 Vector3 vn1 = {v1->y * v2->z - v1->z * v2->y, v1->z * v2->x - v1->x * v2->z, 805 v1->x * v2->y - v1->y * v2->x}; 806 807 // Vector3Normalize(vn1); 808 v = vn1; 809 length = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); 810 if (length == 0.0f) 811 length = 1.0f; 812 ilength = 1.0f / length; 813 vn1.x *= ilength; 814 vn1.y *= ilength; 815 vn1.z *= ilength; 816 817 // Vector3CrossProduct(vn1, *v1) 818 Vector3 vn2 = {vn1.y * v1->z - vn1.z * v1->y, vn1.z * v1->x - vn1.x * v1->z, 819 vn1.x * v1->y - vn1.y * v1->x}; 820 821 *v2 = vn2; 822} 823 824// Transforms a Vector3 by a given Matrix 825RMAPI Vector3 Vector3Transform(Vector3 v, Matrix mat) { 826 Vector3 result = {0}; 827 828 float x = v.x; 829 float y = v.y; 830 float z = v.z; 831 832 result.x = mat.m0 * x + mat.m4 * y + mat.m8 * z + mat.m12; 833 result.y = mat.m1 * x + mat.m5 * y + mat.m9 * z + mat.m13; 834 result.z = mat.m2 * x + mat.m6 * y + mat.m10 * z + mat.m14; 835 836 return result; 837} 838 839// Transform a vector by quaternion rotation 840RMAPI Vector3 Vector3RotateByQuaternion(Vector3 v, Quaternion q) { 841 Vector3 result = {0}; 842 843 result.x = v.x * (q.x * q.x + q.w * q.w - q.y * q.y - q.z * q.z) + 844 v.y * (2 * q.x * q.y - 2 * q.w * q.z) + 845 v.z * (2 * q.x * q.z + 2 * q.w * q.y); 846 result.y = v.x * (2 * q.w * q.z + 2 * q.x * q.y) + 847 v.y * (q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z) + 848 v.z * (-2 * q.w * q.x + 2 * q.y * q.z); 849 result.z = v.x * (-2 * q.w * q.y + 2 * q.x * q.z) + 850 v.y * (2 * q.w * q.x + 2 * q.y * q.z) + 851 v.z * (q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z); 852 853 return result; 854} 855 856// Rotates a vector around an axis 857RMAPI Vector3 Vector3RotateByAxisAngle(Vector3 v, Vector3 axis, float angle) { 858 // Using Euler-Rodrigues Formula 859 // Ref.: 860 // https://en.wikipedia.org/w/index.php?title=Euler%E2%80%93Rodrigues_formula 861 862 Vector3 result = v; 863 864 // Vector3Normalize(axis); 865 float length = sqrtf(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z); 866 if (length == 0.0f) 867 length = 1.0f; 868 float ilength = 1.0f / length; 869 axis.x *= ilength; 870 axis.y *= ilength; 871 axis.z *= ilength; 872 873 angle /= 2.0f; 874 float a = sinf(angle); 875 float b = axis.x * a; 876 float c = axis.y * a; 877 float d = axis.z * a; 878 a = cosf(angle); 879 Vector3 w = {b, c, d}; 880 881 // Vector3CrossProduct(w, v) 882 Vector3 wv = {w.y * v.z - w.z * v.y, w.z * v.x - w.x * v.z, 883 w.x * v.y - w.y * v.x}; 884 885 // Vector3CrossProduct(w, wv) 886 Vector3 wwv = {w.y * wv.z - w.z * wv.y, w.z * wv.x - w.x * wv.z, 887 w.x * wv.y - w.y * wv.x}; 888 889 // Vector3Scale(wv, 2*a) 890 a *= 2; 891 wv.x *= a; 892 wv.y *= a; 893 wv.z *= a; 894 895 // Vector3Scale(wwv, 2) 896 wwv.x *= 2; 897 wwv.y *= 2; 898 wwv.z *= 2; 899 900 result.x += wv.x; 901 result.y += wv.y; 902 result.z += wv.z; 903 904 result.x += wwv.x; 905 result.y += wwv.y; 906 result.z += wwv.z; 907 908 return result; 909} 910 911// Move Vector towards target 912RMAPI Vector3 Vector3MoveTowards(Vector3 v, Vector3 target, float maxDistance) { 913 Vector3 result = {0}; 914 915 float dx = target.x - v.x; 916 float dy = target.y - v.y; 917 float dz = target.z - v.z; 918 float value = (dx * dx) + (dy * dy) + (dz * dz); 919 920 if ((value == 0) || 921 ((maxDistance >= 0) && (value <= maxDistance * maxDistance))) 922 return target; 923 924 float dist = sqrtf(value); 925 926 result.x = v.x + dx / dist * maxDistance; 927 result.y = v.y + dy / dist * maxDistance; 928 result.z = v.z + dz / dist * maxDistance; 929 930 return result; 931} 932 933// Calculate linear interpolation between two vectors 934RMAPI Vector3 Vector3Lerp(Vector3 v1, Vector3 v2, float amount) { 935 Vector3 result = {0}; 936 937 result.x = v1.x + amount * (v2.x - v1.x); 938 result.y = v1.y + amount * (v2.y - v1.y); 939 result.z = v1.z + amount * (v2.z - v1.z); 940 941 return result; 942} 943 944// Calculate cubic hermite interpolation between two vectors and their tangents 945// as described in the GLTF 2.0 specification: 946// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic 947RMAPI Vector3 Vector3CubicHermite(Vector3 v1, Vector3 tangent1, Vector3 v2, 948 Vector3 tangent2, float amount) { 949 Vector3 result = {0}; 950 951 float amountPow2 = amount * amount; 952 float amountPow3 = amount * amount * amount; 953 954 result.x = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.x + 955 (amountPow3 - 2 * amountPow2 + amount) * tangent1.x + 956 (-2 * amountPow3 + 3 * amountPow2) * v2.x + 957 (amountPow3 - amountPow2) * tangent2.x; 958 result.y = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.y + 959 (amountPow3 - 2 * amountPow2 + amount) * tangent1.y + 960 (-2 * amountPow3 + 3 * amountPow2) * v2.y + 961 (amountPow3 - amountPow2) * tangent2.y; 962 result.z = (2 * amountPow3 - 3 * amountPow2 + 1) * v1.z + 963 (amountPow3 - 2 * amountPow2 + amount) * tangent1.z + 964 (-2 * amountPow3 + 3 * amountPow2) * v2.z + 965 (amountPow3 - amountPow2) * tangent2.z; 966 967 return result; 968} 969 970// Calculate reflected vector to normal 971RMAPI Vector3 Vector3Reflect(Vector3 v, Vector3 normal) { 972 Vector3 result = {0}; 973 974 // I is the original vector 975 // N is the normal of the incident plane 976 // R = I - (2*N*(DotProduct[I, N])) 977 978 float dotProduct = (v.x * normal.x + v.y * normal.y + v.z * normal.z); 979 980 result.x = v.x - (2.0f * normal.x) * dotProduct; 981 result.y = v.y - (2.0f * normal.y) * dotProduct; 982 result.z = v.z - (2.0f * normal.z) * dotProduct; 983 984 return result; 985} 986 987// Get min value for each pair of components 988RMAPI Vector3 Vector3Min(Vector3 v1, Vector3 v2) { 989 Vector3 result = {0}; 990 991 result.x = fminf(v1.x, v2.x); 992 result.y = fminf(v1.y, v2.y); 993 result.z = fminf(v1.z, v2.z); 994 995 return result; 996} 997 998// Get max value for each pair of components 999RMAPI Vector3 Vector3Max(Vector3 v1, Vector3 v2) { 1000 Vector3 result = {0}; 1001 1002 result.x = fmaxf(v1.x, v2.x); 1003 result.y = fmaxf(v1.y, v2.y); 1004 result.z = fmaxf(v1.z, v2.z); 1005 1006 return result; 1007} 1008 1009// Compute barycenter coordinates (u, v, w) for point p with respect to triangle 1010// (a, b, c) NOTE: Assumes P is on the plane of the triangle 1011RMAPI Vector3 Vector3Barycenter(Vector3 p, Vector3 a, Vector3 b, Vector3 c) { 1012 Vector3 result = {0}; 1013 1014 Vector3 v0 = {b.x - a.x, b.y - a.y, b.z - a.z}; // Vector3Subtract(b, a) 1015 Vector3 v1 = {c.x - a.x, c.y - a.y, c.z - a.z}; // Vector3Subtract(c, a) 1016 Vector3 v2 = {p.x - a.x, p.y - a.y, p.z - a.z}; // Vector3Subtract(p, a) 1017 float d00 = 1018 (v0.x * v0.x + v0.y * v0.y + v0.z * v0.z); // Vector3DotProduct(v0, v0) 1019 float d01 = 1020 (v0.x * v1.x + v0.y * v1.y + v0.z * v1.z); // Vector3DotProduct(v0, v1) 1021 float d11 = 1022 (v1.x * v1.x + v1.y * v1.y + v1.z * v1.z); // Vector3DotProduct(v1, v1) 1023 float d20 = 1024 (v2.x * v0.x + v2.y * v0.y + v2.z * v0.z); // Vector3DotProduct(v2, v0) 1025 float d21 = 1026 (v2.x * v1.x + v2.y * v1.y + v2.z * v1.z); // Vector3DotProduct(v2, v1) 1027 1028 float denom = d00 * d11 - d01 * d01; 1029 1030 result.y = (d11 * d20 - d01 * d21) / denom; 1031 result.z = (d00 * d21 - d01 * d20) / denom; 1032 result.x = 1.0f - (result.z + result.y); 1033 1034 return result; 1035} 1036 1037// Projects a Vector3 from screen space into object space 1038// NOTE: We are avoiding calling other raymath functions despite available 1039RMAPI Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view) { 1040 Vector3 result = {0}; 1041 1042 // Calculate unprojected matrix (multiply view matrix by projection matrix) 1043 // and invert it 1044 Matrix matViewProj = { 1045 // MatrixMultiply(view, projection); 1046 view.m0 * projection.m0 + view.m1 * projection.m4 + 1047 view.m2 * projection.m8 + view.m3 * projection.m12, 1048 view.m0 * projection.m1 + view.m1 * projection.m5 + 1049 view.m2 * projection.m9 + view.m3 * projection.m13, 1050 view.m0 * projection.m2 + view.m1 * projection.m6 + 1051 view.m2 * projection.m10 + view.m3 * projection.m14, 1052 view.m0 * projection.m3 + view.m1 * projection.m7 + 1053 view.m2 * projection.m11 + view.m3 * projection.m15, 1054 view.m4 * projection.m0 + view.m5 * projection.m4 + 1055 view.m6 * projection.m8 + view.m7 * projection.m12, 1056 view.m4 * projection.m1 + view.m5 * projection.m5 + 1057 view.m6 * projection.m9 + view.m7 * projection.m13, 1058 view.m4 * projection.m2 + view.m5 * projection.m6 + 1059 view.m6 * projection.m10 + view.m7 * projection.m14, 1060 view.m4 * projection.m3 + view.m5 * projection.m7 + 1061 view.m6 * projection.m11 + view.m7 * projection.m15, 1062 view.m8 * projection.m0 + view.m9 * projection.m4 + 1063 view.m10 * projection.m8 + view.m11 * projection.m12, 1064 view.m8 * projection.m1 + view.m9 * projection.m5 + 1065 view.m10 * projection.m9 + view.m11 * projection.m13, 1066 view.m8 * projection.m2 + view.m9 * projection.m6 + 1067 view.m10 * projection.m10 + view.m11 * projection.m14, 1068 view.m8 * projection.m3 + view.m9 * projection.m7 + 1069 view.m10 * projection.m11 + view.m11 * projection.m15, 1070 view.m12 * projection.m0 + view.m13 * projection.m4 + 1071 view.m14 * projection.m8 + view.m15 * projection.m12, 1072 view.m12 * projection.m1 + view.m13 * projection.m5 + 1073 view.m14 * projection.m9 + view.m15 * projection.m13, 1074 view.m12 * projection.m2 + view.m13 * projection.m6 + 1075 view.m14 * projection.m10 + view.m15 * projection.m14, 1076 view.m12 * projection.m3 + view.m13 * projection.m7 + 1077 view.m14 * projection.m11 + view.m15 * projection.m15}; 1078 1079 // Calculate inverted matrix -> MatrixInvert(matViewProj); 1080 // Cache the matrix values (speed optimization) 1081 float a00 = matViewProj.m0, a01 = matViewProj.m1, a02 = matViewProj.m2, 1082 a03 = matViewProj.m3; 1083 float a10 = matViewProj.m4, a11 = matViewProj.m5, a12 = matViewProj.m6, 1084 a13 = matViewProj.m7; 1085 float a20 = matViewProj.m8, a21 = matViewProj.m9, a22 = matViewProj.m10, 1086 a23 = matViewProj.m11; 1087 float a30 = matViewProj.m12, a31 = matViewProj.m13, a32 = matViewProj.m14, 1088 a33 = matViewProj.m15; 1089 1090 float b00 = a00 * a11 - a01 * a10; 1091 float b01 = a00 * a12 - a02 * a10; 1092 float b02 = a00 * a13 - a03 * a10; 1093 float b03 = a01 * a12 - a02 * a11; 1094 float b04 = a01 * a13 - a03 * a11; 1095 float b05 = a02 * a13 - a03 * a12; 1096 float b06 = a20 * a31 - a21 * a30; 1097 float b07 = a20 * a32 - a22 * a30; 1098 float b08 = a20 * a33 - a23 * a30; 1099 float b09 = a21 * a32 - a22 * a31; 1100 float b10 = a21 * a33 - a23 * a31; 1101 float b11 = a22 * a33 - a23 * a32; 1102 1103 // Calculate the invert determinant (inlined to avoid double-caching) 1104 float invDet = 1.0f / (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - 1105 b04 * b07 + b05 * b06); 1106 1107 Matrix matViewProjInv = {(a11 * b11 - a12 * b10 + a13 * b09) * invDet, 1108 (-a01 * b11 + a02 * b10 - a03 * b09) * invDet, 1109 (a31 * b05 - a32 * b04 + a33 * b03) * invDet, 1110 (-a21 * b05 + a22 * b04 - a23 * b03) * invDet, 1111 (-a10 * b11 + a12 * b08 - a13 * b07) * invDet, 1112 (a00 * b11 - a02 * b08 + a03 * b07) * invDet, 1113 (-a30 * b05 + a32 * b02 - a33 * b01) * invDet, 1114 (a20 * b05 - a22 * b02 + a23 * b01) * invDet, 1115 (a10 * b10 - a11 * b08 + a13 * b06) * invDet, 1116 (-a00 * b10 + a01 * b08 - a03 * b06) * invDet, 1117 (a30 * b04 - a31 * b02 + a33 * b00) * invDet, 1118 (-a20 * b04 + a21 * b02 - a23 * b00) * invDet, 1119 (-a10 * b09 + a11 * b07 - a12 * b06) * invDet, 1120 (a00 * b09 - a01 * b07 + a02 * b06) * invDet, 1121 (-a30 * b03 + a31 * b01 - a32 * b00) * invDet, 1122 (a20 * b03 - a21 * b01 + a22 * b00) * invDet}; 1123 1124 // Create quaternion from source point 1125 Quaternion quat = {source.x, source.y, source.z, 1.0f}; 1126 1127 // Multiply quat point by unprojecte matrix 1128 Quaternion qtransformed = { 1129 // QuaternionTransform(quat, matViewProjInv) 1130 matViewProjInv.m0 * quat.x + matViewProjInv.m4 * quat.y + 1131 matViewProjInv.m8 * quat.z + matViewProjInv.m12 * quat.w, 1132 matViewProjInv.m1 * quat.x + matViewProjInv.m5 * quat.y + 1133 matViewProjInv.m9 * quat.z + matViewProjInv.m13 * quat.w, 1134 matViewProjInv.m2 * quat.x + matViewProjInv.m6 * quat.y + 1135 matViewProjInv.m10 * quat.z + matViewProjInv.m14 * quat.w, 1136 matViewProjInv.m3 * quat.x + matViewProjInv.m7 * quat.y + 1137 matViewProjInv.m11 * quat.z + matViewProjInv.m15 * quat.w}; 1138 1139 // Normalized world points in vectors 1140 result.x = qtransformed.x / qtransformed.w; 1141 result.y = qtransformed.y / qtransformed.w; 1142 result.z = qtransformed.z / qtransformed.w; 1143 1144 return result; 1145} 1146 1147// Get Vector3 as float array 1148RMAPI float3 Vector3ToFloatV(Vector3 v) { 1149 float3 buffer = {0}; 1150 1151 buffer.v[0] = v.x; 1152 buffer.v[1] = v.y; 1153 buffer.v[2] = v.z; 1154 1155 return buffer; 1156} 1157 1158// Invert the given vector 1159RMAPI Vector3 Vector3Invert(Vector3 v) { 1160 Vector3 result = {1.0f / v.x, 1.0f / v.y, 1.0f / v.z}; 1161 1162 return result; 1163} 1164 1165// Clamp the components of the vector between 1166// min and max values specified by the given vectors 1167RMAPI Vector3 Vector3Clamp(Vector3 v, Vector3 min, Vector3 max) { 1168 Vector3 result = {0}; 1169 1170 result.x = fminf(max.x, fmaxf(min.x, v.x)); 1171 result.y = fminf(max.y, fmaxf(min.y, v.y)); 1172 result.z = fminf(max.z, fmaxf(min.z, v.z)); 1173 1174 return result; 1175} 1176 1177// Clamp the magnitude of the vector between two values 1178RMAPI Vector3 Vector3ClampValue(Vector3 v, float min, float max) { 1179 Vector3 result = v; 1180 1181 float length = (v.x * v.x) + (v.y * v.y) + (v.z * v.z); 1182 if (length > 0.0f) { 1183 length = sqrtf(length); 1184 1185 float scale = 1; // By default, 1 as the neutral element. 1186 if (length < min) { 1187 scale = min / length; 1188 } else if (length > max) { 1189 scale = max / length; 1190 } 1191 1192 result.x = v.x * scale; 1193 result.y = v.y * scale; 1194 result.z = v.z * scale; 1195 } 1196 1197 return result; 1198} 1199 1200// Check whether two given vectors are almost equal 1201RMAPI int Vector3Equals(Vector3 p, Vector3 q) { 1202#if !defined(EPSILON) 1203#define EPSILON 0.000001f 1204#endif 1205 1206 int result = ((fabsf(p.x - q.x)) <= 1207 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 1208 ((fabsf(p.y - q.y)) <= 1209 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && 1210 ((fabsf(p.z - q.z)) <= 1211 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))); 1212 1213 return result; 1214} 1215 1216// Compute the direction of a refracted ray 1217// v: normalized direction of the incoming ray 1218// n: normalized normal vector of the interface of two optical media 1219// r: ratio of the refractive index of the medium from where the ray comes 1220// to the refractive index of the medium on the other side of the surface 1221RMAPI Vector3 Vector3Refract(Vector3 v, Vector3 n, float r) { 1222 Vector3 result = {0}; 1223 1224 float dot = v.x * n.x + v.y * n.y + v.z * n.z; 1225 float d = 1.0f - r * r * (1.0f - dot * dot); 1226 1227 if (d >= 0.0f) { 1228 d = sqrtf(d); 1229 v.x = r * v.x - (r * dot + d) * n.x; 1230 v.y = r * v.y - (r * dot + d) * n.y; 1231 v.z = r * v.z - (r * dot + d) * n.z; 1232 1233 result = v; 1234 } 1235 1236 return result; 1237} 1238 1239//---------------------------------------------------------------------------------- 1240// Module Functions Definition - Vector4 math 1241//---------------------------------------------------------------------------------- 1242 1243RMAPI Vector4 Vector4Zero(void) { 1244 Vector4 result = {0.0f, 0.0f, 0.0f, 0.0f}; 1245 return result; 1246} 1247 1248RMAPI Vector4 Vector4One(void) { 1249 Vector4 result = {1.0f, 1.0f, 1.0f, 1.0f}; 1250 return result; 1251} 1252 1253RMAPI Vector4 Vector4Add(Vector4 v1, Vector4 v2) { 1254 Vector4 result = {v1.x + v2.x, v1.y + v2.y, v1.z + v2.z, v1.w + v2.w}; 1255 return result; 1256} 1257 1258RMAPI Vector4 Vector4AddValue(Vector4 v, float add) { 1259 Vector4 result = {v.x + add, v.y + add, v.z + add, v.w + add}; 1260 return result; 1261} 1262 1263RMAPI Vector4 Vector4Subtract(Vector4 v1, Vector4 v2) { 1264 Vector4 result = {v1.x - v2.x, v1.y - v2.y, v1.z - v2.z, v1.w - v2.w}; 1265 return result; 1266} 1267 1268RMAPI Vector4 Vector4SubtractValue(Vector4 v, float add) { 1269 Vector4 result = {v.x - add, v.y - add, v.z - add, v.w - add}; 1270 return result; 1271} 1272 1273RMAPI float Vector4Length(Vector4 v) { 1274 float result = sqrtf((v.x * v.x) + (v.y * v.y) + (v.z * v.z) + (v.w * v.w)); 1275 return result; 1276} 1277 1278RMAPI float Vector4LengthSqr(Vector4 v) { 1279 float result = (v.x * v.x) + (v.y * v.y) + (v.z * v.z) + (v.w * v.w); 1280 return result; 1281} 1282 1283RMAPI float Vector4DotProduct(Vector4 v1, Vector4 v2) { 1284 float result = (v1.x * v2.x + v1.y * v2.y + v1.z * v2.z + v1.w * v2.w); 1285 return result; 1286} 1287 1288// Calculate distance between two vectors 1289RMAPI float Vector4Distance(Vector4 v1, Vector4 v2) { 1290 float result = 1291 sqrtf((v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y) + 1292 (v1.z - v2.z) * (v1.z - v2.z) + (v1.w - v2.w) * (v1.w - v2.w)); 1293 return result; 1294} 1295 1296// Calculate square distance between two vectors 1297RMAPI float Vector4DistanceSqr(Vector4 v1, Vector4 v2) { 1298 float result = (v1.x - v2.x) * (v1.x - v2.x) + (v1.y - v2.y) * (v1.y - v2.y) + 1299 (v1.z - v2.z) * (v1.z - v2.z) + (v1.w - v2.w) * (v1.w - v2.w); 1300 1301 return result; 1302} 1303 1304RMAPI Vector4 Vector4Scale(Vector4 v, float scale) { 1305 Vector4 result = {v.x * scale, v.y * scale, v.z * scale, v.w * scale}; 1306 return result; 1307} 1308 1309// Multiply vector by vector 1310RMAPI Vector4 Vector4Multiply(Vector4 v1, Vector4 v2) { 1311 Vector4 result = {v1.x * v2.x, v1.y * v2.y, v1.z * v2.z, v1.w * v2.w}; 1312 return result; 1313} 1314 1315// Negate vector 1316RMAPI Vector4 Vector4Negate(Vector4 v) { 1317 Vector4 result = {-v.x, -v.y, -v.z, -v.w}; 1318 return result; 1319} 1320 1321// Divide vector by vector 1322RMAPI Vector4 Vector4Divide(Vector4 v1, Vector4 v2) { 1323 Vector4 result = {v1.x / v2.x, v1.y / v2.y, v1.z / v2.z, v1.w / v2.w}; 1324 return result; 1325} 1326 1327// Normalize provided vector 1328RMAPI Vector4 Vector4Normalize(Vector4 v) { 1329 Vector4 result = {0}; 1330 float length = sqrtf((v.x * v.x) + (v.y * v.y) + (v.z * v.z) + (v.w * v.w)); 1331 1332 if (length > 0) { 1333 float ilength = 1.0f / length; 1334 result.x = v.x * ilength; 1335 result.y = v.y * ilength; 1336 result.z = v.z * ilength; 1337 result.w = v.w * ilength; 1338 } 1339 1340 return result; 1341} 1342 1343// Get min value for each pair of components 1344RMAPI Vector4 Vector4Min(Vector4 v1, Vector4 v2) { 1345 Vector4 result = {0}; 1346 1347 result.x = fminf(v1.x, v2.x); 1348 result.y = fminf(v1.y, v2.y); 1349 result.z = fminf(v1.z, v2.z); 1350 result.w = fminf(v1.w, v2.w); 1351 1352 return result; 1353} 1354 1355// Get max value for each pair of components 1356RMAPI Vector4 Vector4Max(Vector4 v1, Vector4 v2) { 1357 Vector4 result = {0}; 1358 1359 result.x = fmaxf(v1.x, v2.x); 1360 result.y = fmaxf(v1.y, v2.y); 1361 result.z = fmaxf(v1.z, v2.z); 1362 result.w = fmaxf(v1.w, v2.w); 1363 1364 return result; 1365} 1366 1367// Calculate linear interpolation between two vectors 1368RMAPI Vector4 Vector4Lerp(Vector4 v1, Vector4 v2, float amount) { 1369 Vector4 result = {0}; 1370 1371 result.x = v1.x + amount * (v2.x - v1.x); 1372 result.y = v1.y + amount * (v2.y - v1.y); 1373 result.z = v1.z + amount * (v2.z - v1.z); 1374 result.w = v1.w + amount * (v2.w - v1.w); 1375 1376 return result; 1377} 1378 1379// Move Vector towards target 1380RMAPI Vector4 Vector4MoveTowards(Vector4 v, Vector4 target, float maxDistance) { 1381 Vector4 result = {0}; 1382 1383 float dx = target.x - v.x; 1384 float dy = target.y - v.y; 1385 float dz = target.z - v.z; 1386 float dw = target.w - v.w; 1387 float value = (dx * dx) + (dy * dy) + (dz * dz) + (dw * dw); 1388 1389 if ((value == 0) || 1390 ((maxDistance >= 0) && (value <= maxDistance * maxDistance))) 1391 return target; 1392 1393 float dist = sqrtf(value); 1394 1395 result.x = v.x + dx / dist * maxDistance; 1396 result.y = v.y + dy / dist * maxDistance; 1397 result.z = v.z + dz / dist * maxDistance; 1398 result.w = v.w + dw / dist * maxDistance; 1399 1400 return result; 1401} 1402 1403// Invert the given vector 1404RMAPI Vector4 Vector4Invert(Vector4 v) { 1405 Vector4 result = {1.0f / v.x, 1.0f / v.y, 1.0f / v.z, 1.0f / v.w}; 1406 return result; 1407} 1408 1409// Check whether two given vectors are almost equal 1410RMAPI int Vector4Equals(Vector4 p, Vector4 q) { 1411#if !defined(EPSILON) 1412#define EPSILON 0.000001f 1413#endif 1414 1415 int result = ((fabsf(p.x - q.x)) <= 1416 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 1417 ((fabsf(p.y - q.y)) <= 1418 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && 1419 ((fabsf(p.z - q.z)) <= 1420 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && 1421 ((fabsf(p.w - q.w)) <= 1422 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w))))); 1423 return result; 1424} 1425 1426//---------------------------------------------------------------------------------- 1427// Module Functions Definition - Matrix math 1428//---------------------------------------------------------------------------------- 1429 1430// Compute matrix determinant 1431RMAPI float MatrixDeterminant(Matrix mat) { 1432 float result = 0.0f; 1433 /* 1434 // Cache the matrix values (speed optimization) 1435 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; 1436 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; 1437 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; 1438 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; 1439 1440 // NOTE: It takes 72 multiplication to calculate 4x4 matrix determinant 1441 result = a30*a21*a12*a03 - a20*a31*a12*a03 - a30*a11*a22*a03 + 1442 a10*a31*a22*a03 + a20*a11*a32*a03 - a10*a21*a32*a03 - a30*a21*a02*a13 + 1443 a20*a31*a02*a13 + a30*a01*a22*a13 - a00*a31*a22*a13 - a20*a01*a32*a13 + 1444 a00*a21*a32*a13 + a30*a11*a02*a23 - a10*a31*a02*a23 - a30*a01*a12*a23 + 1445 a00*a31*a12*a23 + a10*a01*a32*a23 - a00*a11*a32*a23 - a20*a11*a02*a33 + 1446 a10*a21*a02*a33 + a20*a01*a12*a33 - a00*a21*a12*a33 - a10*a01*a22*a33 + 1447 a00*a11*a22*a33; 1448 */ 1449 // Using Laplace expansion (https://en.wikipedia.org/wiki/Laplace_expansion), 1450 // previous operation can be simplified to 40 multiplications, decreasing 1451 // matrix size from 4x4 to 2x2 using minors 1452 1453 // Cache the matrix values (speed optimization) 1454 float m0 = mat.m0, m1 = mat.m1, m2 = mat.m2, m3 = mat.m3; 1455 float m4 = mat.m4, m5 = mat.m5, m6 = mat.m6, m7 = mat.m7; 1456 float m8 = mat.m8, m9 = mat.m9, m10 = mat.m10, m11 = mat.m11; 1457 float m12 = mat.m12, m13 = mat.m13, m14 = mat.m14, m15 = mat.m15; 1458 1459 result = (m0 * ((m5 * (m10 * m15 - m11 * m14) - m9 * (m6 * m15 - m7 * m14) + 1460 m13 * (m6 * m11 - m7 * m10))) - 1461 m4 * ((m1 * (m10 * m15 - m11 * m14) - m9 * (m2 * m15 - m3 * m14) + 1462 m13 * (m2 * m11 - m3 * m10))) + 1463 m8 * ((m1 * (m6 * m15 - m7 * m14) - m5 * (m2 * m15 - m3 * m14) + 1464 m13 * (m2 * m7 - m3 * m6))) - 1465 m12 * ((m1 * (m6 * m11 - m7 * m10) - m5 * (m2 * m11 - m3 * m10) + 1466 m9 * (m2 * m7 - m3 * m6)))); 1467 1468 return result; 1469} 1470 1471// Get the trace of the matrix (sum of the values along the diagonal) 1472RMAPI float MatrixTrace(Matrix mat) { 1473 float result = (mat.m0 + mat.m5 + mat.m10 + mat.m15); 1474 1475 return result; 1476} 1477 1478// Transposes provided matrix 1479RMAPI Matrix MatrixTranspose(Matrix mat) { 1480 Matrix result = {0}; 1481 1482 result.m0 = mat.m0; 1483 result.m1 = mat.m4; 1484 result.m2 = mat.m8; 1485 result.m3 = mat.m12; 1486 result.m4 = mat.m1; 1487 result.m5 = mat.m5; 1488 result.m6 = mat.m9; 1489 result.m7 = mat.m13; 1490 result.m8 = mat.m2; 1491 result.m9 = mat.m6; 1492 result.m10 = mat.m10; 1493 result.m11 = mat.m14; 1494 result.m12 = mat.m3; 1495 result.m13 = mat.m7; 1496 result.m14 = mat.m11; 1497 result.m15 = mat.m15; 1498 1499 return result; 1500} 1501 1502// Invert provided matrix 1503RMAPI Matrix MatrixInvert(Matrix mat) { 1504 Matrix result = {0}; 1505 1506 // Cache the matrix values (speed optimization) 1507 float a00 = mat.m0, a01 = mat.m1, a02 = mat.m2, a03 = mat.m3; 1508 float a10 = mat.m4, a11 = mat.m5, a12 = mat.m6, a13 = mat.m7; 1509 float a20 = mat.m8, a21 = mat.m9, a22 = mat.m10, a23 = mat.m11; 1510 float a30 = mat.m12, a31 = mat.m13, a32 = mat.m14, a33 = mat.m15; 1511 1512 float b00 = a00 * a11 - a01 * a10; 1513 float b01 = a00 * a12 - a02 * a10; 1514 float b02 = a00 * a13 - a03 * a10; 1515 float b03 = a01 * a12 - a02 * a11; 1516 float b04 = a01 * a13 - a03 * a11; 1517 float b05 = a02 * a13 - a03 * a12; 1518 float b06 = a20 * a31 - a21 * a30; 1519 float b07 = a20 * a32 - a22 * a30; 1520 float b08 = a20 * a33 - a23 * a30; 1521 float b09 = a21 * a32 - a22 * a31; 1522 float b10 = a21 * a33 - a23 * a31; 1523 float b11 = a22 * a33 - a23 * a32; 1524 1525 // Calculate the invert determinant (inlined to avoid double-caching) 1526 float invDet = 1.0f / (b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - 1527 b04 * b07 + b05 * b06); 1528 1529 result.m0 = (a11 * b11 - a12 * b10 + a13 * b09) * invDet; 1530 result.m1 = (-a01 * b11 + a02 * b10 - a03 * b09) * invDet; 1531 result.m2 = (a31 * b05 - a32 * b04 + a33 * b03) * invDet; 1532 result.m3 = (-a21 * b05 + a22 * b04 - a23 * b03) * invDet; 1533 result.m4 = (-a10 * b11 + a12 * b08 - a13 * b07) * invDet; 1534 result.m5 = (a00 * b11 - a02 * b08 + a03 * b07) * invDet; 1535 result.m6 = (-a30 * b05 + a32 * b02 - a33 * b01) * invDet; 1536 result.m7 = (a20 * b05 - a22 * b02 + a23 * b01) * invDet; 1537 result.m8 = (a10 * b10 - a11 * b08 + a13 * b06) * invDet; 1538 result.m9 = (-a00 * b10 + a01 * b08 - a03 * b06) * invDet; 1539 result.m10 = (a30 * b04 - a31 * b02 + a33 * b00) * invDet; 1540 result.m11 = (-a20 * b04 + a21 * b02 - a23 * b00) * invDet; 1541 result.m12 = (-a10 * b09 + a11 * b07 - a12 * b06) * invDet; 1542 result.m13 = (a00 * b09 - a01 * b07 + a02 * b06) * invDet; 1543 result.m14 = (-a30 * b03 + a31 * b01 - a32 * b00) * invDet; 1544 result.m15 = (a20 * b03 - a21 * b01 + a22 * b00) * invDet; 1545 1546 return result; 1547} 1548 1549// Get identity matrix 1550RMAPI Matrix MatrixIdentity(void) { 1551 Matrix result = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1552 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; 1553 1554 return result; 1555} 1556 1557// Add two matrices 1558RMAPI Matrix MatrixAdd(Matrix left, Matrix right) { 1559 Matrix result = {0}; 1560 1561 result.m0 = left.m0 + right.m0; 1562 result.m1 = left.m1 + right.m1; 1563 result.m2 = left.m2 + right.m2; 1564 result.m3 = left.m3 + right.m3; 1565 result.m4 = left.m4 + right.m4; 1566 result.m5 = left.m5 + right.m5; 1567 result.m6 = left.m6 + right.m6; 1568 result.m7 = left.m7 + right.m7; 1569 result.m8 = left.m8 + right.m8; 1570 result.m9 = left.m9 + right.m9; 1571 result.m10 = left.m10 + right.m10; 1572 result.m11 = left.m11 + right.m11; 1573 result.m12 = left.m12 + right.m12; 1574 result.m13 = left.m13 + right.m13; 1575 result.m14 = left.m14 + right.m14; 1576 result.m15 = left.m15 + right.m15; 1577 1578 return result; 1579} 1580 1581// Subtract two matrices (left - right) 1582RMAPI Matrix MatrixSubtract(Matrix left, Matrix right) { 1583 Matrix result = {0}; 1584 1585 result.m0 = left.m0 - right.m0; 1586 result.m1 = left.m1 - right.m1; 1587 result.m2 = left.m2 - right.m2; 1588 result.m3 = left.m3 - right.m3; 1589 result.m4 = left.m4 - right.m4; 1590 result.m5 = left.m5 - right.m5; 1591 result.m6 = left.m6 - right.m6; 1592 result.m7 = left.m7 - right.m7; 1593 result.m8 = left.m8 - right.m8; 1594 result.m9 = left.m9 - right.m9; 1595 result.m10 = left.m10 - right.m10; 1596 result.m11 = left.m11 - right.m11; 1597 result.m12 = left.m12 - right.m12; 1598 result.m13 = left.m13 - right.m13; 1599 result.m14 = left.m14 - right.m14; 1600 result.m15 = left.m15 - right.m15; 1601 1602 return result; 1603} 1604 1605// Get two matrix multiplication 1606// NOTE: When multiplying matrices... the order matters! 1607RMAPI Matrix MatrixMultiply(Matrix left, Matrix right) { 1608 Matrix result = {0}; 1609 1610 result.m0 = left.m0 * right.m0 + left.m1 * right.m4 + left.m2 * right.m8 + 1611 left.m3 * right.m12; 1612 result.m1 = left.m0 * right.m1 + left.m1 * right.m5 + left.m2 * right.m9 + 1613 left.m3 * right.m13; 1614 result.m2 = left.m0 * right.m2 + left.m1 * right.m6 + left.m2 * right.m10 + 1615 left.m3 * right.m14; 1616 result.m3 = left.m0 * right.m3 + left.m1 * right.m7 + left.m2 * right.m11 + 1617 left.m3 * right.m15; 1618 result.m4 = left.m4 * right.m0 + left.m5 * right.m4 + left.m6 * right.m8 + 1619 left.m7 * right.m12; 1620 result.m5 = left.m4 * right.m1 + left.m5 * right.m5 + left.m6 * right.m9 + 1621 left.m7 * right.m13; 1622 result.m6 = left.m4 * right.m2 + left.m5 * right.m6 + left.m6 * right.m10 + 1623 left.m7 * right.m14; 1624 result.m7 = left.m4 * right.m3 + left.m5 * right.m7 + left.m6 * right.m11 + 1625 left.m7 * right.m15; 1626 result.m8 = left.m8 * right.m0 + left.m9 * right.m4 + left.m10 * right.m8 + 1627 left.m11 * right.m12; 1628 result.m9 = left.m8 * right.m1 + left.m9 * right.m5 + left.m10 * right.m9 + 1629 left.m11 * right.m13; 1630 result.m10 = left.m8 * right.m2 + left.m9 * right.m6 + left.m10 * right.m10 + 1631 left.m11 * right.m14; 1632 result.m11 = left.m8 * right.m3 + left.m9 * right.m7 + left.m10 * right.m11 + 1633 left.m11 * right.m15; 1634 result.m12 = left.m12 * right.m0 + left.m13 * right.m4 + left.m14 * right.m8 + 1635 left.m15 * right.m12; 1636 result.m13 = left.m12 * right.m1 + left.m13 * right.m5 + left.m14 * right.m9 + 1637 left.m15 * right.m13; 1638 result.m14 = left.m12 * right.m2 + left.m13 * right.m6 + 1639 left.m14 * right.m10 + left.m15 * right.m14; 1640 result.m15 = left.m12 * right.m3 + left.m13 * right.m7 + 1641 left.m14 * right.m11 + left.m15 * right.m15; 1642 1643 return result; 1644} 1645 1646// Get translation matrix 1647RMAPI Matrix MatrixTranslate(float x, float y, float z) { 1648 Matrix result = {1.0f, 0.0f, 0.0f, x, 0.0f, 1.0f, 0.0f, y, 1649 0.0f, 0.0f, 1.0f, z, 0.0f, 0.0f, 0.0f, 1.0f}; 1650 1651 return result; 1652} 1653 1654// Create rotation matrix from axis and angle 1655// NOTE: Angle should be provided in radians 1656RMAPI Matrix MatrixRotate(Vector3 axis, float angle) { 1657 Matrix result = {0}; 1658 1659 float x = axis.x, y = axis.y, z = axis.z; 1660 1661 float lengthSquared = x * x + y * y + z * z; 1662 1663 if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) { 1664 float ilength = 1.0f / sqrtf(lengthSquared); 1665 x *= ilength; 1666 y *= ilength; 1667 z *= ilength; 1668 } 1669 1670 float sinres = sinf(angle); 1671 float cosres = cosf(angle); 1672 float t = 1.0f - cosres; 1673 1674 result.m0 = x * x * t + cosres; 1675 result.m1 = y * x * t + z * sinres; 1676 result.m2 = z * x * t - y * sinres; 1677 result.m3 = 0.0f; 1678 1679 result.m4 = x * y * t - z * sinres; 1680 result.m5 = y * y * t + cosres; 1681 result.m6 = z * y * t + x * sinres; 1682 result.m7 = 0.0f; 1683 1684 result.m8 = x * z * t + y * sinres; 1685 result.m9 = y * z * t - x * sinres; 1686 result.m10 = z * z * t + cosres; 1687 result.m11 = 0.0f; 1688 1689 result.m12 = 0.0f; 1690 result.m13 = 0.0f; 1691 result.m14 = 0.0f; 1692 result.m15 = 1.0f; 1693 1694 return result; 1695} 1696 1697// Get x-rotation matrix 1698// NOTE: Angle must be provided in radians 1699RMAPI Matrix MatrixRotateX(float angle) { 1700 Matrix result = { 1701 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1702 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; // MatrixIdentity() 1703 1704 float cosres = cosf(angle); 1705 float sinres = sinf(angle); 1706 1707 result.m5 = cosres; 1708 result.m6 = sinres; 1709 result.m9 = -sinres; 1710 result.m10 = cosres; 1711 1712 return result; 1713} 1714 1715// Get y-rotation matrix 1716// NOTE: Angle must be provided in radians 1717RMAPI Matrix MatrixRotateY(float angle) { 1718 Matrix result = { 1719 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1720 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; // MatrixIdentity() 1721 1722 float cosres = cosf(angle); 1723 float sinres = sinf(angle); 1724 1725 result.m0 = cosres; 1726 result.m2 = -sinres; 1727 result.m8 = sinres; 1728 result.m10 = cosres; 1729 1730 return result; 1731} 1732 1733// Get z-rotation matrix 1734// NOTE: Angle must be provided in radians 1735RMAPI Matrix MatrixRotateZ(float angle) { 1736 Matrix result = { 1737 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1738 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; // MatrixIdentity() 1739 1740 float cosres = cosf(angle); 1741 float sinres = sinf(angle); 1742 1743 result.m0 = cosres; 1744 result.m1 = sinres; 1745 result.m4 = -sinres; 1746 result.m5 = cosres; 1747 1748 return result; 1749} 1750 1751// Get xyz-rotation matrix 1752// NOTE: Angle must be provided in radians 1753RMAPI Matrix MatrixRotateXYZ(Vector3 angle) { 1754 Matrix result = { 1755 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1756 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; // MatrixIdentity() 1757 1758 float cosz = cosf(-angle.z); 1759 float sinz = sinf(-angle.z); 1760 float cosy = cosf(-angle.y); 1761 float siny = sinf(-angle.y); 1762 float cosx = cosf(-angle.x); 1763 float sinx = sinf(-angle.x); 1764 1765 result.m0 = cosz * cosy; 1766 result.m1 = (cosz * siny * sinx) - (sinz * cosx); 1767 result.m2 = (cosz * siny * cosx) + (sinz * sinx); 1768 1769 result.m4 = sinz * cosy; 1770 result.m5 = (sinz * siny * sinx) + (cosz * cosx); 1771 result.m6 = (sinz * siny * cosx) - (cosz * sinx); 1772 1773 result.m8 = -siny; 1774 result.m9 = cosy * sinx; 1775 result.m10 = cosy * cosx; 1776 1777 return result; 1778} 1779 1780// Get zyx-rotation matrix 1781// NOTE: Angle must be provided in radians 1782RMAPI Matrix MatrixRotateZYX(Vector3 angle) { 1783 Matrix result = {0}; 1784 1785 float cz = cosf(angle.z); 1786 float sz = sinf(angle.z); 1787 float cy = cosf(angle.y); 1788 float sy = sinf(angle.y); 1789 float cx = cosf(angle.x); 1790 float sx = sinf(angle.x); 1791 1792 result.m0 = cz * cy; 1793 result.m4 = cz * sy * sx - cx * sz; 1794 result.m8 = sz * sx + cz * cx * sy; 1795 result.m12 = 0; 1796 1797 result.m1 = cy * sz; 1798 result.m5 = cz * cx + sz * sy * sx; 1799 result.m9 = cx * sz * sy - cz * sx; 1800 result.m13 = 0; 1801 1802 result.m2 = -sy; 1803 result.m6 = cy * sx; 1804 result.m10 = cy * cx; 1805 result.m14 = 0; 1806 1807 result.m3 = 0; 1808 result.m7 = 0; 1809 result.m11 = 0; 1810 result.m15 = 1; 1811 1812 return result; 1813} 1814 1815// Get scaling matrix 1816RMAPI Matrix MatrixScale(float x, float y, float z) { 1817 Matrix result = {x, 0.0f, 0.0f, 0.0f, 0.0f, y, 0.0f, 0.0f, 1818 0.0f, 0.0f, z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; 1819 1820 return result; 1821} 1822 1823// Get perspective projection matrix 1824RMAPI Matrix MatrixFrustum(double left, double right, double bottom, double top, 1825 double nearPlane, double farPlane) { 1826 Matrix result = {0}; 1827 1828 float rl = (float)(right - left); 1829 float tb = (float)(top - bottom); 1830 float fn = (float)(farPlane - nearPlane); 1831 1832 result.m0 = ((float)nearPlane * 2.0f) / rl; 1833 result.m1 = 0.0f; 1834 result.m2 = 0.0f; 1835 result.m3 = 0.0f; 1836 1837 result.m4 = 0.0f; 1838 result.m5 = ((float)nearPlane * 2.0f) / tb; 1839 result.m6 = 0.0f; 1840 result.m7 = 0.0f; 1841 1842 result.m8 = ((float)right + (float)left) / rl; 1843 result.m9 = ((float)top + (float)bottom) / tb; 1844 result.m10 = -((float)farPlane + (float)nearPlane) / fn; 1845 result.m11 = -1.0f; 1846 1847 result.m12 = 0.0f; 1848 result.m13 = 0.0f; 1849 result.m14 = -((float)farPlane * (float)nearPlane * 2.0f) / fn; 1850 result.m15 = 0.0f; 1851 1852 return result; 1853} 1854 1855// Get perspective projection matrix 1856// NOTE: Fovy angle must be provided in radians 1857RMAPI Matrix MatrixPerspective(double fovY, double aspect, double nearPlane, 1858 double farPlane) { 1859 Matrix result = {0}; 1860 1861 double top = nearPlane * tan(fovY * 0.5); 1862 double bottom = -top; 1863 double right = top * aspect; 1864 double left = -right; 1865 1866 // MatrixFrustum(-right, right, -top, top, near, far); 1867 float rl = (float)(right - left); 1868 float tb = (float)(top - bottom); 1869 float fn = (float)(farPlane - nearPlane); 1870 1871 result.m0 = ((float)nearPlane * 2.0f) / rl; 1872 result.m5 = ((float)nearPlane * 2.0f) / tb; 1873 result.m8 = ((float)right + (float)left) / rl; 1874 result.m9 = ((float)top + (float)bottom) / tb; 1875 result.m10 = -((float)farPlane + (float)nearPlane) / fn; 1876 result.m11 = -1.0f; 1877 result.m14 = -((float)farPlane * (float)nearPlane * 2.0f) / fn; 1878 1879 return result; 1880} 1881 1882// Get orthographic projection matrix 1883RMAPI Matrix MatrixOrtho(double left, double right, double bottom, double top, 1884 double nearPlane, double farPlane) { 1885 Matrix result = {0}; 1886 1887 float rl = (float)(right - left); 1888 float tb = (float)(top - bottom); 1889 float fn = (float)(farPlane - nearPlane); 1890 1891 result.m0 = 2.0f / rl; 1892 result.m1 = 0.0f; 1893 result.m2 = 0.0f; 1894 result.m3 = 0.0f; 1895 result.m4 = 0.0f; 1896 result.m5 = 2.0f / tb; 1897 result.m6 = 0.0f; 1898 result.m7 = 0.0f; 1899 result.m8 = 0.0f; 1900 result.m9 = 0.0f; 1901 result.m10 = -2.0f / fn; 1902 result.m11 = 0.0f; 1903 result.m12 = -((float)left + (float)right) / rl; 1904 result.m13 = -((float)top + (float)bottom) / tb; 1905 result.m14 = -((float)farPlane + (float)nearPlane) / fn; 1906 result.m15 = 1.0f; 1907 1908 return result; 1909} 1910 1911// Get camera look-at matrix (view matrix) 1912RMAPI Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) { 1913 Matrix result = {0}; 1914 1915 float length = 0.0f; 1916 float ilength = 0.0f; 1917 1918 // Vector3Subtract(eye, target) 1919 Vector3 vz = {eye.x - target.x, eye.y - target.y, eye.z - target.z}; 1920 1921 // Vector3Normalize(vz) 1922 Vector3 v = vz; 1923 length = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); 1924 if (length == 0.0f) 1925 length = 1.0f; 1926 ilength = 1.0f / length; 1927 vz.x *= ilength; 1928 vz.y *= ilength; 1929 vz.z *= ilength; 1930 1931 // Vector3CrossProduct(up, vz) 1932 Vector3 vx = {up.y * vz.z - up.z * vz.y, up.z * vz.x - up.x * vz.z, 1933 up.x * vz.y - up.y * vz.x}; 1934 1935 // Vector3Normalize(x) 1936 v = vx; 1937 length = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z); 1938 if (length == 0.0f) 1939 length = 1.0f; 1940 ilength = 1.0f / length; 1941 vx.x *= ilength; 1942 vx.y *= ilength; 1943 vx.z *= ilength; 1944 1945 // Vector3CrossProduct(vz, vx) 1946 Vector3 vy = {vz.y * vx.z - vz.z * vx.y, vz.z * vx.x - vz.x * vx.z, 1947 vz.x * vx.y - vz.y * vx.x}; 1948 1949 result.m0 = vx.x; 1950 result.m1 = vy.x; 1951 result.m2 = vz.x; 1952 result.m3 = 0.0f; 1953 result.m4 = vx.y; 1954 result.m5 = vy.y; 1955 result.m6 = vz.y; 1956 result.m7 = 0.0f; 1957 result.m8 = vx.z; 1958 result.m9 = vy.z; 1959 result.m10 = vz.z; 1960 result.m11 = 0.0f; 1961 result.m12 = -(vx.x * eye.x + vx.y * eye.y + 1962 vx.z * eye.z); // Vector3DotProduct(vx, eye) 1963 result.m13 = -(vy.x * eye.x + vy.y * eye.y + 1964 vy.z * eye.z); // Vector3DotProduct(vy, eye) 1965 result.m14 = -(vz.x * eye.x + vz.y * eye.y + 1966 vz.z * eye.z); // Vector3DotProduct(vz, eye) 1967 result.m15 = 1.0f; 1968 1969 return result; 1970} 1971 1972// Get float array of matrix data 1973RMAPI float16 MatrixToFloatV(Matrix mat) { 1974 float16 result = {0}; 1975 1976 result.v[0] = mat.m0; 1977 result.v[1] = mat.m1; 1978 result.v[2] = mat.m2; 1979 result.v[3] = mat.m3; 1980 result.v[4] = mat.m4; 1981 result.v[5] = mat.m5; 1982 result.v[6] = mat.m6; 1983 result.v[7] = mat.m7; 1984 result.v[8] = mat.m8; 1985 result.v[9] = mat.m9; 1986 result.v[10] = mat.m10; 1987 result.v[11] = mat.m11; 1988 result.v[12] = mat.m12; 1989 result.v[13] = mat.m13; 1990 result.v[14] = mat.m14; 1991 result.v[15] = mat.m15; 1992 1993 return result; 1994} 1995 1996//---------------------------------------------------------------------------------- 1997// Module Functions Definition - Quaternion math 1998//---------------------------------------------------------------------------------- 1999 2000// Add two quaternions 2001RMAPI Quaternion QuaternionAdd(Quaternion q1, Quaternion q2) { 2002 Quaternion result = {q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w}; 2003 2004 return result; 2005} 2006 2007// Add quaternion and float value 2008RMAPI Quaternion QuaternionAddValue(Quaternion q, float add) { 2009 Quaternion result = {q.x + add, q.y + add, q.z + add, q.w + add}; 2010 2011 return result; 2012} 2013 2014// Subtract two quaternions 2015RMAPI Quaternion QuaternionSubtract(Quaternion q1, Quaternion q2) { 2016 Quaternion result = {q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w}; 2017 2018 return result; 2019} 2020 2021// Subtract quaternion and float value 2022RMAPI Quaternion QuaternionSubtractValue(Quaternion q, float sub) { 2023 Quaternion result = {q.x - sub, q.y - sub, q.z - sub, q.w - sub}; 2024 2025 return result; 2026} 2027 2028// Get identity quaternion 2029RMAPI Quaternion QuaternionIdentity(void) { 2030 Quaternion result = {0.0f, 0.0f, 0.0f, 1.0f}; 2031 2032 return result; 2033} 2034 2035// Computes the length of a quaternion 2036RMAPI float QuaternionLength(Quaternion q) { 2037 float result = sqrtf(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); 2038 2039 return result; 2040} 2041 2042// Normalize provided quaternion 2043RMAPI Quaternion QuaternionNormalize(Quaternion q) { 2044 Quaternion result = {0}; 2045 2046 float length = sqrtf(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); 2047 if (length == 0.0f) 2048 length = 1.0f; 2049 float ilength = 1.0f / length; 2050 2051 result.x = q.x * ilength; 2052 result.y = q.y * ilength; 2053 result.z = q.z * ilength; 2054 result.w = q.w * ilength; 2055 2056 return result; 2057} 2058 2059// Invert provided quaternion 2060RMAPI Quaternion QuaternionInvert(Quaternion q) { 2061 Quaternion result = q; 2062 2063 float lengthSq = q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w; 2064 2065 if (lengthSq != 0.0f) { 2066 float invLength = 1.0f / lengthSq; 2067 2068 result.x *= -invLength; 2069 result.y *= -invLength; 2070 result.z *= -invLength; 2071 result.w *= invLength; 2072 } 2073 2074 return result; 2075} 2076 2077// Calculate two quaternion multiplication 2078RMAPI Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) { 2079 Quaternion result = {0}; 2080 2081 float qax = q1.x, qay = q1.y, qaz = q1.z, qaw = q1.w; 2082 float qbx = q2.x, qby = q2.y, qbz = q2.z, qbw = q2.w; 2083 2084 result.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 2085 result.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 2086 result.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 2087 result.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 2088 2089 return result; 2090} 2091 2092// Scale quaternion by float value 2093RMAPI Quaternion QuaternionScale(Quaternion q, float mul) { 2094 Quaternion result = {0}; 2095 2096 result.x = q.x * mul; 2097 result.y = q.y * mul; 2098 result.z = q.z * mul; 2099 result.w = q.w * mul; 2100 2101 return result; 2102} 2103 2104// Divide two quaternions 2105RMAPI Quaternion QuaternionDivide(Quaternion q1, Quaternion q2) { 2106 Quaternion result = {q1.x / q2.x, q1.y / q2.y, q1.z / q2.z, q1.w / q2.w}; 2107 2108 return result; 2109} 2110 2111// Calculate linear interpolation between two quaternions 2112RMAPI Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount) { 2113 Quaternion result = {0}; 2114 2115 result.x = q1.x + amount * (q2.x - q1.x); 2116 result.y = q1.y + amount * (q2.y - q1.y); 2117 result.z = q1.z + amount * (q2.z - q1.z); 2118 result.w = q1.w + amount * (q2.w - q1.w); 2119 2120 return result; 2121} 2122 2123// Calculate slerp-optimized interpolation between two quaternions 2124RMAPI Quaternion QuaternionNlerp(Quaternion q1, Quaternion q2, float amount) { 2125 Quaternion result = {0}; 2126 2127 // QuaternionLerp(q1, q2, amount) 2128 result.x = q1.x + amount * (q2.x - q1.x); 2129 result.y = q1.y + amount * (q2.y - q1.y); 2130 result.z = q1.z + amount * (q2.z - q1.z); 2131 result.w = q1.w + amount * (q2.w - q1.w); 2132 2133 // QuaternionNormalize(q); 2134 Quaternion q = result; 2135 float length = sqrtf(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); 2136 if (length == 0.0f) 2137 length = 1.0f; 2138 float ilength = 1.0f / length; 2139 2140 result.x = q.x * ilength; 2141 result.y = q.y * ilength; 2142 result.z = q.z * ilength; 2143 result.w = q.w * ilength; 2144 2145 return result; 2146} 2147 2148// Calculates spherical linear interpolation between two quaternions 2149RMAPI Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) { 2150 Quaternion result = {0}; 2151 2152#if !defined(EPSILON) 2153#define EPSILON 0.000001f 2154#endif 2155 2156 float cosHalfTheta = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w; 2157 2158 if (cosHalfTheta < 0) { 2159 q2.x = -q2.x; 2160 q2.y = -q2.y; 2161 q2.z = -q2.z; 2162 q2.w = -q2.w; 2163 cosHalfTheta = -cosHalfTheta; 2164 } 2165 2166 if (fabsf(cosHalfTheta) >= 1.0f) 2167 result = q1; 2168 else if (cosHalfTheta > 0.95f) 2169 result = QuaternionNlerp(q1, q2, amount); 2170 else { 2171 float halfTheta = acosf(cosHalfTheta); 2172 float sinHalfTheta = sqrtf(1.0f - cosHalfTheta * cosHalfTheta); 2173 2174 if (fabsf(sinHalfTheta) < EPSILON) { 2175 result.x = (q1.x * 0.5f + q2.x * 0.5f); 2176 result.y = (q1.y * 0.5f + q2.y * 0.5f); 2177 result.z = (q1.z * 0.5f + q2.z * 0.5f); 2178 result.w = (q1.w * 0.5f + q2.w * 0.5f); 2179 } else { 2180 float ratioA = sinf((1 - amount) * halfTheta) / sinHalfTheta; 2181 float ratioB = sinf(amount * halfTheta) / sinHalfTheta; 2182 2183 result.x = (q1.x * ratioA + q2.x * ratioB); 2184 result.y = (q1.y * ratioA + q2.y * ratioB); 2185 result.z = (q1.z * ratioA + q2.z * ratioB); 2186 result.w = (q1.w * ratioA + q2.w * ratioB); 2187 } 2188 } 2189 2190 return result; 2191} 2192 2193// Calculate quaternion cubic spline interpolation using Cubic Hermite Spline 2194// algorithm as described in the GLTF 2.0 specification: 2195// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#interpolation-cubic 2196RMAPI Quaternion QuaternionCubicHermiteSpline(Quaternion q1, 2197 Quaternion outTangent1, 2198 Quaternion q2, 2199 Quaternion inTangent2, float t) { 2200 float t2 = t * t; 2201 float t3 = t2 * t; 2202 float h00 = 2 * t3 - 3 * t2 + 1; 2203 float h10 = t3 - 2 * t2 + t; 2204 float h01 = -2 * t3 + 3 * t2; 2205 float h11 = t3 - t2; 2206 2207 Quaternion p0 = QuaternionScale(q1, h00); 2208 Quaternion m0 = QuaternionScale(outTangent1, h10); 2209 Quaternion p1 = QuaternionScale(q2, h01); 2210 Quaternion m1 = QuaternionScale(inTangent2, h11); 2211 2212 Quaternion result = {0}; 2213 2214 result = QuaternionAdd(p0, m0); 2215 result = QuaternionAdd(result, p1); 2216 result = QuaternionAdd(result, m1); 2217 result = QuaternionNormalize(result); 2218 2219 return result; 2220} 2221 2222// Calculate quaternion based on the rotation from one vector to another 2223RMAPI Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) { 2224 Quaternion result = {0}; 2225 2226 float cos2Theta = (from.x * to.x + from.y * to.y + 2227 from.z * to.z); // Vector3DotProduct(from, to) 2228 Vector3 cross = {from.y * to.z - from.z * to.y, from.z * to.x - from.x * to.z, 2229 from.x * to.y - 2230 from.y * to.x}; // Vector3CrossProduct(from, to) 2231 2232 result.x = cross.x; 2233 result.y = cross.y; 2234 result.z = cross.z; 2235 result.w = 1.0f + cos2Theta; 2236 2237 // QuaternionNormalize(q); 2238 // NOTE: Normalize to essentially nlerp the original and identity to 0.5 2239 Quaternion q = result; 2240 float length = sqrtf(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); 2241 if (length == 0.0f) 2242 length = 1.0f; 2243 float ilength = 1.0f / length; 2244 2245 result.x = q.x * ilength; 2246 result.y = q.y * ilength; 2247 result.z = q.z * ilength; 2248 result.w = q.w * ilength; 2249 2250 return result; 2251} 2252 2253// Get a quaternion for a given rotation matrix 2254RMAPI Quaternion QuaternionFromMatrix(Matrix mat) { 2255 Quaternion result = {0}; 2256 2257 float fourWSquaredMinus1 = mat.m0 + mat.m5 + mat.m10; 2258 float fourXSquaredMinus1 = mat.m0 - mat.m5 - mat.m10; 2259 float fourYSquaredMinus1 = mat.m5 - mat.m0 - mat.m10; 2260 float fourZSquaredMinus1 = mat.m10 - mat.m0 - mat.m5; 2261 2262 int biggestIndex = 0; 2263 float fourBiggestSquaredMinus1 = fourWSquaredMinus1; 2264 if (fourXSquaredMinus1 > fourBiggestSquaredMinus1) { 2265 fourBiggestSquaredMinus1 = fourXSquaredMinus1; 2266 biggestIndex = 1; 2267 } 2268 2269 if (fourYSquaredMinus1 > fourBiggestSquaredMinus1) { 2270 fourBiggestSquaredMinus1 = fourYSquaredMinus1; 2271 biggestIndex = 2; 2272 } 2273 2274 if (fourZSquaredMinus1 > fourBiggestSquaredMinus1) { 2275 fourBiggestSquaredMinus1 = fourZSquaredMinus1; 2276 biggestIndex = 3; 2277 } 2278 2279 float biggestVal = sqrtf(fourBiggestSquaredMinus1 + 1.0f) * 0.5f; 2280 float mult = 0.25f / biggestVal; 2281 2282 switch (biggestIndex) { 2283 case 0: 2284 result.w = biggestVal; 2285 result.x = (mat.m6 - mat.m9) * mult; 2286 result.y = (mat.m8 - mat.m2) * mult; 2287 result.z = (mat.m1 - mat.m4) * mult; 2288 break; 2289 case 1: 2290 result.x = biggestVal; 2291 result.w = (mat.m6 - mat.m9) * mult; 2292 result.y = (mat.m1 + mat.m4) * mult; 2293 result.z = (mat.m8 + mat.m2) * mult; 2294 break; 2295 case 2: 2296 result.y = biggestVal; 2297 result.w = (mat.m8 - mat.m2) * mult; 2298 result.x = (mat.m1 + mat.m4) * mult; 2299 result.z = (mat.m6 + mat.m9) * mult; 2300 break; 2301 case 3: 2302 result.z = biggestVal; 2303 result.w = (mat.m1 - mat.m4) * mult; 2304 result.x = (mat.m8 + mat.m2) * mult; 2305 result.y = (mat.m6 + mat.m9) * mult; 2306 break; 2307 } 2308 2309 return result; 2310} 2311 2312// Get a matrix for a given quaternion 2313RMAPI Matrix QuaternionToMatrix(Quaternion q) { 2314 Matrix result = { 2315 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 2316 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}; // MatrixIdentity() 2317 2318 float a2 = q.x * q.x; 2319 float b2 = q.y * q.y; 2320 float c2 = q.z * q.z; 2321 float ac = q.x * q.z; 2322 float ab = q.x * q.y; 2323 float bc = q.y * q.z; 2324 float ad = q.w * q.x; 2325 float bd = q.w * q.y; 2326 float cd = q.w * q.z; 2327 2328 result.m0 = 1 - 2 * (b2 + c2); 2329 result.m1 = 2 * (ab + cd); 2330 result.m2 = 2 * (ac - bd); 2331 2332 result.m4 = 2 * (ab - cd); 2333 result.m5 = 1 - 2 * (a2 + c2); 2334 result.m6 = 2 * (bc + ad); 2335 2336 result.m8 = 2 * (ac + bd); 2337 result.m9 = 2 * (bc - ad); 2338 result.m10 = 1 - 2 * (a2 + b2); 2339 2340 return result; 2341} 2342 2343// Get rotation quaternion for an angle and axis 2344// NOTE: Angle must be provided in radians 2345RMAPI Quaternion QuaternionFromAxisAngle(Vector3 axis, float angle) { 2346 Quaternion result = {0.0f, 0.0f, 0.0f, 1.0f}; 2347 2348 float axisLength = sqrtf(axis.x * axis.x + axis.y * axis.y + axis.z * axis.z); 2349 2350 if (axisLength != 0.0f) { 2351 angle *= 0.5f; 2352 2353 float length = 0.0f; 2354 float ilength = 0.0f; 2355 2356 // Vector3Normalize(axis) 2357 length = axisLength; 2358 if (length == 0.0f) 2359 length = 1.0f; 2360 ilength = 1.0f / length; 2361 axis.x *= ilength; 2362 axis.y *= ilength; 2363 axis.z *= ilength; 2364 2365 float sinres = sinf(angle); 2366 float cosres = cosf(angle); 2367 2368 result.x = axis.x * sinres; 2369 result.y = axis.y * sinres; 2370 result.z = axis.z * sinres; 2371 result.w = cosres; 2372 2373 // QuaternionNormalize(q); 2374 Quaternion q = result; 2375 length = sqrtf(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); 2376 if (length == 0.0f) 2377 length = 1.0f; 2378 ilength = 1.0f / length; 2379 result.x = q.x * ilength; 2380 result.y = q.y * ilength; 2381 result.z = q.z * ilength; 2382 result.w = q.w * ilength; 2383 } 2384 2385 return result; 2386} 2387 2388// Get the rotation angle and axis for a given quaternion 2389RMAPI void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, 2390 float *outAngle) { 2391 if (fabsf(q.w) > 1.0f) { 2392 // QuaternionNormalize(q); 2393 float length = sqrtf(q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w); 2394 if (length == 0.0f) 2395 length = 1.0f; 2396 float ilength = 1.0f / length; 2397 2398 q.x = q.x * ilength; 2399 q.y = q.y * ilength; 2400 q.z = q.z * ilength; 2401 q.w = q.w * ilength; 2402 } 2403 2404 Vector3 resAxis = {0.0f, 0.0f, 0.0f}; 2405 float resAngle = 2.0f * acosf(q.w); 2406 float den = sqrtf(1.0f - q.w * q.w); 2407 2408 if (den > EPSILON) { 2409 resAxis.x = q.x / den; 2410 resAxis.y = q.y / den; 2411 resAxis.z = q.z / den; 2412 } else { 2413 // This occurs when the angle is zero. 2414 // Not a problem: just set an arbitrary normalized axis. 2415 resAxis.x = 1.0f; 2416 } 2417 2418 *outAxis = resAxis; 2419 *outAngle = resAngle; 2420} 2421 2422// Get the quaternion equivalent to Euler angles 2423// NOTE: Rotation order is ZYX 2424RMAPI Quaternion QuaternionFromEuler(float pitch, float yaw, float roll) { 2425 Quaternion result = {0}; 2426 2427 float x0 = cosf(pitch * 0.5f); 2428 float x1 = sinf(pitch * 0.5f); 2429 float y0 = cosf(yaw * 0.5f); 2430 float y1 = sinf(yaw * 0.5f); 2431 float z0 = cosf(roll * 0.5f); 2432 float z1 = sinf(roll * 0.5f); 2433 2434 result.x = x1 * y0 * z0 - x0 * y1 * z1; 2435 result.y = x0 * y1 * z0 + x1 * y0 * z1; 2436 result.z = x0 * y0 * z1 - x1 * y1 * z0; 2437 result.w = x0 * y0 * z0 + x1 * y1 * z1; 2438 2439 return result; 2440} 2441 2442// Get the Euler angles equivalent to quaternion (roll, pitch, yaw) 2443// NOTE: Angles are returned in a Vector3 struct in radians 2444RMAPI Vector3 QuaternionToEuler(Quaternion q) { 2445 Vector3 result = {0}; 2446 2447 // Roll (x-axis rotation) 2448 float x0 = 2.0f * (q.w * q.x + q.y * q.z); 2449 float x1 = 1.0f - 2.0f * (q.x * q.x + q.y * q.y); 2450 result.x = atan2f(x0, x1); 2451 2452 // Pitch (y-axis rotation) 2453 float y0 = 2.0f * (q.w * q.y - q.z * q.x); 2454 y0 = y0 > 1.0f ? 1.0f : y0; 2455 y0 = y0 < -1.0f ? -1.0f : y0; 2456 result.y = asinf(y0); 2457 2458 // Yaw (z-axis rotation) 2459 float z0 = 2.0f * (q.w * q.z + q.x * q.y); 2460 float z1 = 1.0f - 2.0f * (q.y * q.y + q.z * q.z); 2461 result.z = atan2f(z0, z1); 2462 2463 return result; 2464} 2465 2466// Transform a quaternion given a transformation matrix 2467RMAPI Quaternion QuaternionTransform(Quaternion q, Matrix mat) { 2468 Quaternion result = {0}; 2469 2470 result.x = mat.m0 * q.x + mat.m4 * q.y + mat.m8 * q.z + mat.m12 * q.w; 2471 result.y = mat.m1 * q.x + mat.m5 * q.y + mat.m9 * q.z + mat.m13 * q.w; 2472 result.z = mat.m2 * q.x + mat.m6 * q.y + mat.m10 * q.z + mat.m14 * q.w; 2473 result.w = mat.m3 * q.x + mat.m7 * q.y + mat.m11 * q.z + mat.m15 * q.w; 2474 2475 return result; 2476} 2477 2478// Check whether two given quaternions are almost equal 2479RMAPI int QuaternionEquals(Quaternion p, Quaternion q) { 2480#if !defined(EPSILON) 2481#define EPSILON 0.000001f 2482#endif 2483 2484 int result = (((fabsf(p.x - q.x)) <= 2485 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 2486 ((fabsf(p.y - q.y)) <= 2487 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && 2488 ((fabsf(p.z - q.z)) <= 2489 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && 2490 ((fabsf(p.w - q.w)) <= 2491 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))) || 2492 (((fabsf(p.x + q.x)) <= 2493 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.x), fabsf(q.x))))) && 2494 ((fabsf(p.y + q.y)) <= 2495 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.y), fabsf(q.y))))) && 2496 ((fabsf(p.z + q.z)) <= 2497 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.z), fabsf(q.z))))) && 2498 ((fabsf(p.w + q.w)) <= 2499 (EPSILON * fmaxf(1.0f, fmaxf(fabsf(p.w), fabsf(q.w)))))); 2500 2501 return result; 2502} 2503 2504// Decompose a transformation matrix into its rotational, translational and 2505// scaling components and remove shear 2506RMAPI void MatrixDecompose(Matrix mat, Vector3 *translation, 2507 Quaternion *rotation, Vector3 *scale) { 2508 float eps = (float)1e-9; 2509 2510 // Extract Translation 2511 translation->x = mat.m12; 2512 translation->y = mat.m13; 2513 translation->z = mat.m14; 2514 2515 // Matrix Columns - Rotation will be extracted into here. 2516 Vector3 matColumns[3] = {{mat.m0, mat.m4, mat.m8}, 2517 {mat.m1, mat.m5, mat.m9}, 2518 {mat.m2, mat.m6, mat.m10}}; 2519 2520 // Shear Parameters XY, XZ, and YZ (extract and ignored) 2521 float shear[3] = {0}; 2522 2523 // Normalized Scale Parameters 2524 Vector3 scl = {0}; 2525 2526 // Max-Normalizing helps numerical stability 2527 float stabilizer = eps; 2528 for (int i = 0; i < 3; i++) { 2529 stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].x)); 2530 stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].y)); 2531 stabilizer = fmaxf(stabilizer, fabsf(matColumns[i].z)); 2532 }; 2533 matColumns[0] = Vector3Scale(matColumns[0], 1.0f / stabilizer); 2534 matColumns[1] = Vector3Scale(matColumns[1], 1.0f / stabilizer); 2535 matColumns[2] = Vector3Scale(matColumns[2], 1.0f / stabilizer); 2536 2537 // X Scale 2538 scl.x = Vector3Length(matColumns[0]); 2539 if (scl.x > eps) { 2540 matColumns[0] = Vector3Scale(matColumns[0], 1.0f / scl.x); 2541 } 2542 2543 // Compute XY shear and make col2 orthogonal 2544 shear[0] = Vector3DotProduct(matColumns[0], matColumns[1]); 2545 matColumns[1] = 2546 Vector3Subtract(matColumns[1], Vector3Scale(matColumns[0], shear[0])); 2547 2548 // Y Scale 2549 scl.y = Vector3Length(matColumns[1]); 2550 if (scl.y > eps) { 2551 matColumns[1] = Vector3Scale(matColumns[1], 1.0f / scl.y); 2552 shear[0] /= scl.y; // Correct XY shear 2553 } 2554 2555 // Compute XZ and YZ shears and make col3 orthogonal 2556 shear[1] = Vector3DotProduct(matColumns[0], matColumns[2]); 2557 matColumns[2] = 2558 Vector3Subtract(matColumns[2], Vector3Scale(matColumns[0], shear[1])); 2559 shear[2] = Vector3DotProduct(matColumns[1], matColumns[2]); 2560 matColumns[2] = 2561 Vector3Subtract(matColumns[2], Vector3Scale(matColumns[1], shear[2])); 2562 2563 // Z Scale 2564 scl.z = Vector3Length(matColumns[2]); 2565 if (scl.z > eps) { 2566 matColumns[2] = Vector3Scale(matColumns[2], 1.0f / scl.z); 2567 shear[1] /= scl.z; // Correct XZ shear 2568 shear[2] /= scl.z; // Correct YZ shear 2569 } 2570 2571 // matColumns are now orthonormal in O(3). Now ensure its in SO(3) by 2572 // enforcing det = 1. 2573 if (Vector3DotProduct(matColumns[0], Vector3CrossProduct( 2574 matColumns[1], matColumns[2])) < 0) { 2575 scl = Vector3Negate(scl); 2576 matColumns[0] = Vector3Negate(matColumns[0]); 2577 matColumns[1] = Vector3Negate(matColumns[1]); 2578 matColumns[2] = Vector3Negate(matColumns[2]); 2579 } 2580 2581 // Set Scale 2582 *scale = Vector3Scale(scl, stabilizer); 2583 2584 // Extract Rotation 2585 Matrix rotationMatrix = {matColumns[0].x, 2586 matColumns[0].y, 2587 matColumns[0].z, 2588 0, 2589 matColumns[1].x, 2590 matColumns[1].y, 2591 matColumns[1].z, 2592 0, 2593 matColumns[2].x, 2594 matColumns[2].y, 2595 matColumns[2].z, 2596 0, 2597 0, 2598 0, 2599 0, 2600 1}; 2601 *rotation = QuaternionFromMatrix(rotationMatrix); 2602} 2603 2604#if defined(__cplusplus) && !defined(RAYMATH_DISABLE_CPP_OPERATORS) 2605 2606// Optional C++ math operators 2607//------------------------------------------------------------------------------- 2608 2609// Vector2 operators 2610static constexpr Vector2 Vector2Zeros = {0, 0}; 2611static constexpr Vector2 Vector2Ones = {1, 1}; 2612static constexpr Vector2 Vector2UnitX = {1, 0}; 2613static constexpr Vector2 Vector2UnitY = {0, 1}; 2614 2615inline Vector2 operator+(const Vector2 &lhs, const Vector2 &rhs) { 2616 return Vector2Add(lhs, rhs); 2617} 2618 2619inline const Vector2 &operator+=(Vector2 &lhs, const Vector2 &rhs) { 2620 lhs = Vector2Add(lhs, rhs); 2621 return lhs; 2622} 2623 2624inline Vector2 operator-(const Vector2 &lhs, const Vector2 &rhs) { 2625 return Vector2Subtract(lhs, rhs); 2626} 2627 2628inline const Vector2 &operator-=(Vector2 &lhs, const Vector2 &rhs) { 2629 lhs = Vector2Subtract(lhs, rhs); 2630 return lhs; 2631} 2632 2633inline Vector2 operator*(const Vector2 &lhs, const float &rhs) { 2634 return Vector2Scale(lhs, rhs); 2635} 2636 2637inline const Vector2 &operator*=(Vector2 &lhs, const float &rhs) { 2638 lhs = Vector2Scale(lhs, rhs); 2639 return lhs; 2640} 2641 2642inline Vector2 operator*(const Vector2 &lhs, const Vector2 &rhs) { 2643 return Vector2Multiply(lhs, rhs); 2644} 2645 2646inline const Vector2 &operator*=(Vector2 &lhs, const Vector2 &rhs) { 2647 lhs = Vector2Multiply(lhs, rhs); 2648 return lhs; 2649} 2650 2651inline Vector2 operator*(const Vector2 &lhs, const Matrix &rhs) { 2652 return Vector2Transform(lhs, rhs); 2653} 2654 2655inline const Vector2 &operator*=(Vector2 &lhs, const Matrix &rhs) { 2656 lhs = Vector2Transform(lhs, rhs); 2657 return lhs; 2658} 2659 2660inline Vector2 operator/(const Vector2 &lhs, const float &rhs) { 2661 return Vector2Scale(lhs, 1.0f / rhs); 2662} 2663 2664inline const Vector2 &operator/=(Vector2 &lhs, const float &rhs) { 2665 lhs = Vector2Scale(lhs, 1.0f / rhs); 2666 return lhs; 2667} 2668 2669inline Vector2 operator/(const Vector2 &lhs, const Vector2 &rhs) { 2670 return Vector2Divide(lhs, rhs); 2671} 2672 2673inline const Vector2 &operator/=(Vector2 &lhs, const Vector2 &rhs) { 2674 lhs = Vector2Divide(lhs, rhs); 2675 return lhs; 2676} 2677 2678inline bool operator==(const Vector2 &lhs, const Vector2 &rhs) { 2679 return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y); 2680} 2681 2682inline bool operator!=(const Vector2 &lhs, const Vector2 &rhs) { 2683 return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y); 2684} 2685 2686// Vector3 operators 2687static constexpr Vector3 Vector3Zeros = {0, 0, 0}; 2688static constexpr Vector3 Vector3Ones = {1, 1, 1}; 2689static constexpr Vector3 Vector3UnitX = {1, 0, 0}; 2690static constexpr Vector3 Vector3UnitY = {0, 1, 0}; 2691static constexpr Vector3 Vector3UnitZ = {0, 0, 1}; 2692 2693inline Vector3 operator+(const Vector3 &lhs, const Vector3 &rhs) { 2694 return Vector3Add(lhs, rhs); 2695} 2696 2697inline const Vector3 &operator+=(Vector3 &lhs, const Vector3 &rhs) { 2698 lhs = Vector3Add(lhs, rhs); 2699 return lhs; 2700} 2701 2702inline Vector3 operator-(const Vector3 &lhs, const Vector3 &rhs) { 2703 return Vector3Subtract(lhs, rhs); 2704} 2705 2706inline const Vector3 &operator-=(Vector3 &lhs, const Vector3 &rhs) { 2707 lhs = Vector3Subtract(lhs, rhs); 2708 return lhs; 2709} 2710 2711inline Vector3 operator*(const Vector3 &lhs, const float &rhs) { 2712 return Vector3Scale(lhs, rhs); 2713} 2714 2715inline const Vector3 &operator*=(Vector3 &lhs, const float &rhs) { 2716 lhs = Vector3Scale(lhs, rhs); 2717 return lhs; 2718} 2719 2720inline Vector3 operator*(const Vector3 &lhs, const Vector3 &rhs) { 2721 return Vector3Multiply(lhs, rhs); 2722} 2723 2724inline const Vector3 &operator*=(Vector3 &lhs, const Vector3 &rhs) { 2725 lhs = Vector3Multiply(lhs, rhs); 2726 return lhs; 2727} 2728 2729inline Vector3 operator*(const Vector3 &lhs, const Matrix &rhs) { 2730 return Vector3Transform(lhs, rhs); 2731} 2732 2733inline const Vector3 &operator*=(Vector3 &lhs, const Matrix &rhs) { 2734 lhs = Vector3Transform(lhs, rhs); 2735 return lhs; 2736} 2737 2738inline Vector3 operator/(const Vector3 &lhs, const float &rhs) { 2739 return Vector3Scale(lhs, 1.0f / rhs); 2740} 2741 2742inline const Vector3 &operator/=(Vector3 &lhs, const float &rhs) { 2743 lhs = Vector3Scale(lhs, 1.0f / rhs); 2744 return lhs; 2745} 2746 2747inline Vector3 operator/(const Vector3 &lhs, const Vector3 &rhs) { 2748 return Vector3Divide(lhs, rhs); 2749} 2750 2751inline const Vector3 &operator/=(Vector3 &lhs, const Vector3 &rhs) { 2752 lhs = Vector3Divide(lhs, rhs); 2753 return lhs; 2754} 2755 2756inline bool operator==(const Vector3 &lhs, const Vector3 &rhs) { 2757 return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && 2758 FloatEquals(lhs.z, rhs.z); 2759} 2760 2761inline bool operator!=(const Vector3 &lhs, const Vector3 &rhs) { 2762 return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || 2763 !FloatEquals(lhs.z, rhs.z); 2764} 2765 2766// Vector4 operators 2767static constexpr Vector4 Vector4Zeros = {0, 0, 0, 0}; 2768static constexpr Vector4 Vector4Ones = {1, 1, 1, 1}; 2769static constexpr Vector4 Vector4UnitX = {1, 0, 0, 0}; 2770static constexpr Vector4 Vector4UnitY = {0, 1, 0, 0}; 2771static constexpr Vector4 Vector4UnitZ = {0, 0, 1, 0}; 2772static constexpr Vector4 Vector4UnitW = {0, 0, 0, 1}; 2773 2774inline Vector4 operator+(const Vector4 &lhs, const Vector4 &rhs) { 2775 return Vector4Add(lhs, rhs); 2776} 2777 2778inline const Vector4 &operator+=(Vector4 &lhs, const Vector4 &rhs) { 2779 lhs = Vector4Add(lhs, rhs); 2780 return lhs; 2781} 2782 2783inline Vector4 operator-(const Vector4 &lhs, const Vector4 &rhs) { 2784 return Vector4Subtract(lhs, rhs); 2785} 2786 2787inline const Vector4 &operator-=(Vector4 &lhs, const Vector4 &rhs) { 2788 lhs = Vector4Subtract(lhs, rhs); 2789 return lhs; 2790} 2791 2792inline Vector4 operator*(const Vector4 &lhs, const float &rhs) { 2793 return Vector4Scale(lhs, rhs); 2794} 2795 2796inline const Vector4 &operator*=(Vector4 &lhs, const float &rhs) { 2797 lhs = Vector4Scale(lhs, rhs); 2798 return lhs; 2799} 2800 2801inline Vector4 operator*(const Vector4 &lhs, const Vector4 &rhs) { 2802 return Vector4Multiply(lhs, rhs); 2803} 2804 2805inline const Vector4 &operator*=(Vector4 &lhs, const Vector4 &rhs) { 2806 lhs = Vector4Multiply(lhs, rhs); 2807 return lhs; 2808} 2809 2810inline Vector4 operator/(const Vector4 &lhs, const float &rhs) { 2811 return Vector4Scale(lhs, 1.0f / rhs); 2812} 2813 2814inline const Vector4 &operator/=(Vector4 &lhs, const float &rhs) { 2815 lhs = Vector4Scale(lhs, 1.0f / rhs); 2816 return lhs; 2817} 2818 2819inline Vector4 operator/(const Vector4 &lhs, const Vector4 &rhs) { 2820 return Vector4Divide(lhs, rhs); 2821} 2822 2823inline const Vector4 &operator/=(Vector4 &lhs, const Vector4 &rhs) { 2824 lhs = Vector4Divide(lhs, rhs); 2825 return lhs; 2826} 2827 2828inline bool operator==(const Vector4 &lhs, const Vector4 &rhs) { 2829 return FloatEquals(lhs.x, rhs.x) && FloatEquals(lhs.y, rhs.y) && 2830 FloatEquals(lhs.z, rhs.z) && FloatEquals(lhs.w, rhs.w); 2831} 2832 2833inline bool operator!=(const Vector4 &lhs, const Vector4 &rhs) { 2834 return !FloatEquals(lhs.x, rhs.x) || !FloatEquals(lhs.y, rhs.y) || 2835 !FloatEquals(lhs.z, rhs.z) || !FloatEquals(lhs.w, rhs.w); 2836} 2837 2838// Quaternion operators 2839static constexpr Quaternion QuaternionZeros = {0, 0, 0, 0}; 2840static constexpr Quaternion QuaternionOnes = {1, 1, 1, 1}; 2841static constexpr Quaternion QuaternionUnitX = {0, 0, 0, 1}; 2842 2843inline Quaternion operator+(const Quaternion &lhs, const float &rhs) { 2844 return QuaternionAddValue(lhs, rhs); 2845} 2846 2847inline const Quaternion &operator+=(Quaternion &lhs, const float &rhs) { 2848 lhs = QuaternionAddValue(lhs, rhs); 2849 return lhs; 2850} 2851 2852inline Quaternion operator-(const Quaternion &lhs, const float &rhs) { 2853 return QuaternionSubtractValue(lhs, rhs); 2854} 2855 2856inline const Quaternion &operator-=(Quaternion &lhs, const float &rhs) { 2857 lhs = QuaternionSubtractValue(lhs, rhs); 2858 return lhs; 2859} 2860 2861inline Quaternion operator*(const Quaternion &lhs, const Matrix &rhs) { 2862 return QuaternionTransform(lhs, rhs); 2863} 2864 2865inline const Quaternion &operator*=(Quaternion &lhs, const Matrix &rhs) { 2866 lhs = QuaternionTransform(lhs, rhs); 2867 return lhs; 2868} 2869 2870// Matrix operators 2871inline Matrix operator+(const Matrix &lhs, const Matrix &rhs) { 2872 return MatrixAdd(lhs, rhs); 2873} 2874 2875inline const Matrix &operator+=(Matrix &lhs, const Matrix &rhs) { 2876 lhs = MatrixAdd(lhs, rhs); 2877 return lhs; 2878} 2879 2880inline Matrix operator-(const Matrix &lhs, const Matrix &rhs) { 2881 return MatrixSubtract(lhs, rhs); 2882} 2883 2884inline const Matrix &operator-=(Matrix &lhs, const Matrix &rhs) { 2885 lhs = MatrixSubtract(lhs, rhs); 2886 return lhs; 2887} 2888 2889inline Matrix operator*(const Matrix &lhs, const Matrix &rhs) { 2890 return MatrixMultiply(lhs, rhs); 2891} 2892 2893inline const Matrix &operator*=(Matrix &lhs, const Matrix &rhs) { 2894 lhs = MatrixMultiply(lhs, rhs); 2895 return lhs; 2896} 2897//------------------------------------------------------------------------------- 2898#endif // C++ operators 2899 2900#endif // RAYMATH_H