GCC Code Coverage Report


Directory: ./
File: submodules/raylib/src/raymath.h
Date: 2023-09-29 04:53:15
Exec Total Coverage
Lines: 0 921 0.0%
Branches: 0 141 0.0%

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