QUOTE: Let your heart guide you always.

freezo

A retro platform game

raymath.h (63013B)


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