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