diff options
Diffstat (limited to 'libs/raylib/src/raymath.h')
-rw-r--r-- | libs/raylib/src/raymath.h | 502 |
1 files changed, 323 insertions, 179 deletions
diff --git a/libs/raylib/src/raymath.h b/libs/raylib/src/raymath.h index 68d0824..e396d5a 100644 --- a/libs/raylib/src/raymath.h +++ b/libs/raylib/src/raymath.h @@ -20,7 +20,7 @@ * * LICENSE: zlib/libpng * -* Copyright (c) 2015-2020 Ramon Santamaria (@raysan5) +* Copyright (c) 2015-2021 Ramon Santamaria (@raysan5) * * This software is provided "as-is", without any express or implied warranty. In no event * will the authors be held liable for any damages arising from the use of this software. @@ -75,7 +75,7 @@ // Defines and Macros //---------------------------------------------------------------------------------- #ifndef PI - #define PI 3.14159265358979323846 + #define PI 3.14159265358979323846f #endif #ifndef DEG2RAD @@ -114,13 +114,16 @@ float z; } Vector3; - // Quaternion type - typedef struct Quaternion { + // Vector4 type + typedef struct Vector4 { float x; float y; float z; float w; - } Quaternion; + } Vector4; + + // Quaternion type + typedef Vector4 Quaternion; // Matrix type (OpenGL style 4x4 - right handed, column major) typedef struct Matrix { @@ -154,6 +157,18 @@ RMDEF float Lerp(float start, float end, float amount) return start + amount*(end - start); } +// Normalize input value within input range +RMDEF float Normalize(float value, float start, float end) +{ + return (value - start)/(end - start); +} + +// Remap input value within input range to output range +RMDEF float Remap(float value, float inputStart, float inputEnd, float outputStart, float outputEnd) +{ + return (value - inputStart)/(inputEnd - inputStart)*(outputEnd - outputStart) + outputStart; +} + //---------------------------------------------------------------------------------- // Module Functions Definition - Vector2 math //---------------------------------------------------------------------------------- @@ -179,6 +194,13 @@ RMDEF Vector2 Vector2Add(Vector2 v1, Vector2 v2) return result; } +// Add vector and float value +RMDEF Vector2 Vector2AddValue(Vector2 v, float add) +{ + Vector2 result = { v.x + add, v.y + add }; + return result; +} + // Subtract two vectors (v1 - v2) RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) { @@ -186,6 +208,13 @@ RMDEF Vector2 Vector2Subtract(Vector2 v1, Vector2 v2) return result; } +// Subtract vector by float value +RMDEF Vector2 Vector2SubtractValue(Vector2 v, float sub) +{ + Vector2 result = { v.x - sub, v.y - sub }; + return result; +} + // Calculate vector length RMDEF float Vector2Length(Vector2 v) { @@ -193,6 +222,13 @@ RMDEF float Vector2Length(Vector2 v) return result; } +// Calculate vector square length +RMDEF float Vector2LengthSqr(Vector2 v) +{ + float result = (v.x*v.x) + (v.y*v.y); + return result; +} + // Calculate two vectors dot product RMDEF float Vector2DotProduct(Vector2 v1, Vector2 v2) { @@ -223,7 +259,7 @@ RMDEF Vector2 Vector2Scale(Vector2 v, float scale) } // Multiply vector by vector -RMDEF Vector2 Vector2MultiplyV(Vector2 v1, Vector2 v2) +RMDEF Vector2 Vector2Multiply(Vector2 v1, Vector2 v2) { Vector2 result = { v1.x*v2.x, v1.y*v2.y }; return result; @@ -236,15 +272,8 @@ RMDEF Vector2 Vector2Negate(Vector2 v) return result; } -// Divide vector by a float value -RMDEF Vector2 Vector2Divide(Vector2 v, float div) -{ - Vector2 result = { v.x/div, v.y/div }; - return result; -} - // Divide vector by vector -RMDEF Vector2 Vector2DivideV(Vector2 v1, Vector2 v2) +RMDEF Vector2 Vector2Divide(Vector2 v1, Vector2 v2) { Vector2 result = { v1.x/v2.x, v1.y/v2.y }; return result; @@ -253,7 +282,7 @@ RMDEF Vector2 Vector2DivideV(Vector2 v1, Vector2 v2) // Normalize provided vector RMDEF Vector2 Vector2Normalize(Vector2 v) { - Vector2 result = Vector2Divide(v, Vector2Length(v)); + Vector2 result = Vector2Scale(v, 1/Vector2Length(v)); return result; } @@ -268,11 +297,42 @@ RMDEF Vector2 Vector2Lerp(Vector2 v1, Vector2 v2, float amount) return result; } +// Calculate reflected vector to normal +RMDEF Vector2 Vector2Reflect(Vector2 v, Vector2 normal) +{ + Vector2 result = { 0 }; + + float dotProduct = Vector2DotProduct(v, normal); + + result.x = v.x - (2.0f*normal.x)*dotProduct; + result.y = v.y - (2.0f*normal.y)*dotProduct; + + return result; +} + // Rotate Vector by float in Degrees. RMDEF Vector2 Vector2Rotate(Vector2 v, float degs) { float rads = degs*DEG2RAD; - Vector2 result = {v.x * cosf(rads) - v.y * sinf(rads) , v.x * sinf(rads) + v.y * cosf(rads) }; + Vector2 result = {v.x*cosf(rads) - v.y*sinf(rads) , v.x*sinf(rads) + v.y*cosf(rads) }; + return result; +} + +// Move Vector towards target +RMDEF Vector2 Vector2MoveTowards(Vector2 v, Vector2 target, float maxDistance) +{ + Vector2 result = { 0 }; + float dx = target.x - v.x; + float dy = target.y - v.y; + float value = (dx*dx) + (dy*dy); + + if ((value == 0) || ((maxDistance >= 0) && (value <= maxDistance*maxDistance))) result = target; + + float dist = sqrtf(value); + + result.x = v.x + dx/dist*maxDistance; + result.y = v.y + dy/dist*maxDistance; + return result; } @@ -301,6 +361,13 @@ RMDEF Vector3 Vector3Add(Vector3 v1, Vector3 v2) return result; } +// Add vector and float value +RMDEF Vector3 Vector3AddValue(Vector3 v, float add) +{ + Vector3 result = { v.x + add, v.y + add, v.z + add }; + return result; +} + // Subtract two vectors RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) { @@ -308,6 +375,13 @@ RMDEF Vector3 Vector3Subtract(Vector3 v1, Vector3 v2) return result; } +// Subtract vector by float value +RMDEF Vector3 Vector3SubtractValue(Vector3 v, float sub) +{ + Vector3 result = { v.x - sub, v.y - sub, v.z - sub }; + return result; +} + // Multiply vector by scalar RMDEF Vector3 Vector3Scale(Vector3 v, float scalar) { @@ -362,6 +436,13 @@ RMDEF float Vector3Length(const Vector3 v) return result; } +// Calculate vector square length +RMDEF float Vector3LengthSqr(const Vector3 v) +{ + float result = v.x*v.x + v.y*v.y + v.z*v.z; + return result; +} + // Calculate two vectors dot product RMDEF float Vector3DotProduct(Vector3 v1, Vector3 v2) { @@ -386,15 +467,8 @@ RMDEF Vector3 Vector3Negate(Vector3 v) return result; } -// Divide vector by a float value -RMDEF Vector3 Vector3Divide(Vector3 v, float div) -{ - Vector3 result = { v.x / div, v.y / div, v.z / div }; - return result; -} - // Divide vector by vector -RMDEF Vector3 Vector3DivideV(Vector3 v1, Vector3 v2) +RMDEF Vector3 Vector3Divide(Vector3 v1, Vector3 v2) { Vector3 result = { v1.x/v2.x, v1.y/v2.y, v1.z/v2.z }; return result; @@ -737,6 +811,32 @@ RMDEF Matrix MatrixSubtract(Matrix left, Matrix right) return result; } +// Returns two matrix multiplication +// NOTE: When multiplying matrices... the order matters! +RMDEF Matrix MatrixMultiply(Matrix left, Matrix right) +{ + Matrix result = { 0 }; + + result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; + result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; + result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; + result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; + result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; + result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; + result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; + result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; + result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; + result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; + result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; + result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; + result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; + result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; + result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; + result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; + + return result; +} + // Returns translation matrix RMDEF Matrix MatrixTranslate(float x, float y, float z) { @@ -756,14 +856,14 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle) float x = axis.x, y = axis.y, z = axis.z; - float length = sqrtf(x*x + y*y + z*z); + float lengthSquared = x*x + y*y + z*z; - if ((length != 1.0f) && (length != 0.0f)) + if ((lengthSquared != 1.0f) && (lengthSquared != 0.0f)) { - length = 1.0f/length; - x *= length; - y *= length; - z *= length; + float inverseLength = 1.0f/sqrtf(lengthSquared); + x *= inverseLength; + y *= inverseLength; + z *= inverseLength; } float sinres = sinf(angle); @@ -793,33 +893,6 @@ RMDEF Matrix MatrixRotate(Vector3 axis, float angle) return result; } -// Returns xyz-rotation matrix (angles in radians) -RMDEF Matrix MatrixRotateXYZ(Vector3 ang) -{ - Matrix result = MatrixIdentity(); - - float cosz = cosf(-ang.z); - float sinz = sinf(-ang.z); - float cosy = cosf(-ang.y); - float siny = sinf(-ang.y); - float cosx = cosf(-ang.x); - float sinx = sinf(-ang.x); - - result.m0 = cosz * cosy; - result.m4 = (cosz * siny * sinx) - (sinz * cosx); - result.m8 = (cosz * siny * cosx) + (sinz * sinx); - - result.m1 = sinz * cosy; - result.m5 = (sinz * siny * sinx) + (cosz * cosx); - result.m9 = (sinz * siny * cosx) - (cosz * sinx); - - result.m2 = -siny; - result.m6 = cosy * sinx; - result.m10= cosy * cosx; - - return result; -} - // Returns x-rotation matrix (angle in radians) RMDEF Matrix MatrixRotateX(float angle) { @@ -868,39 +941,76 @@ RMDEF Matrix MatrixRotateZ(float angle) return result; } -// Returns scaling matrix -RMDEF Matrix MatrixScale(float x, float y, float z) + +// Returns xyz-rotation matrix (angles in radians) +RMDEF Matrix MatrixRotateXYZ(Vector3 ang) { - Matrix result = { x, 0.0f, 0.0f, 0.0f, - 0.0f, y, 0.0f, 0.0f, - 0.0f, 0.0f, z, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f }; + Matrix result = MatrixIdentity(); + + float cosz = cosf(-ang.z); + float sinz = sinf(-ang.z); + float cosy = cosf(-ang.y); + float siny = sinf(-ang.y); + float cosx = cosf(-ang.x); + float sinx = sinf(-ang.x); + + result.m0 = cosz*cosy; + result.m4 = (cosz*siny*sinx) - (sinz*cosx); + result.m8 = (cosz*siny*cosx) + (sinz*sinx); + + result.m1 = sinz*cosy; + result.m5 = (sinz*siny*sinx) + (cosz*cosx); + result.m9 = (sinz*siny*cosx) - (cosz*sinx); + + result.m2 = -siny; + result.m6 = cosy*sinx; + result.m10= cosy*cosx; return result; } -// Returns two matrix multiplication -// NOTE: When multiplying matrices... the order matters! -RMDEF Matrix MatrixMultiply(Matrix left, Matrix right) +// Returns zyx-rotation matrix (angles in radians) +RMDEF Matrix MatrixRotateZYX(Vector3 ang) { Matrix result = { 0 }; - result.m0 = left.m0*right.m0 + left.m1*right.m4 + left.m2*right.m8 + left.m3*right.m12; - result.m1 = left.m0*right.m1 + left.m1*right.m5 + left.m2*right.m9 + left.m3*right.m13; - result.m2 = left.m0*right.m2 + left.m1*right.m6 + left.m2*right.m10 + left.m3*right.m14; - result.m3 = left.m0*right.m3 + left.m1*right.m7 + left.m2*right.m11 + left.m3*right.m15; - result.m4 = left.m4*right.m0 + left.m5*right.m4 + left.m6*right.m8 + left.m7*right.m12; - result.m5 = left.m4*right.m1 + left.m5*right.m5 + left.m6*right.m9 + left.m7*right.m13; - result.m6 = left.m4*right.m2 + left.m5*right.m6 + left.m6*right.m10 + left.m7*right.m14; - result.m7 = left.m4*right.m3 + left.m5*right.m7 + left.m6*right.m11 + left.m7*right.m15; - result.m8 = left.m8*right.m0 + left.m9*right.m4 + left.m10*right.m8 + left.m11*right.m12; - result.m9 = left.m8*right.m1 + left.m9*right.m5 + left.m10*right.m9 + left.m11*right.m13; - result.m10 = left.m8*right.m2 + left.m9*right.m6 + left.m10*right.m10 + left.m11*right.m14; - result.m11 = left.m8*right.m3 + left.m9*right.m7 + left.m10*right.m11 + left.m11*right.m15; - result.m12 = left.m12*right.m0 + left.m13*right.m4 + left.m14*right.m8 + left.m15*right.m12; - result.m13 = left.m12*right.m1 + left.m13*right.m5 + left.m14*right.m9 + left.m15*right.m13; - result.m14 = left.m12*right.m2 + left.m13*right.m6 + left.m14*right.m10 + left.m15*right.m14; - result.m15 = left.m12*right.m3 + left.m13*right.m7 + left.m14*right.m11 + left.m15*right.m15; + float cz = cosf(ang.z); + float sz = sinf(ang.z); + float cy = cosf(ang.y); + float sy = sinf(ang.y); + float cx = cosf(ang.x); + float sx = sinf(ang.x); + + result.m0 = cz*cy; + result.m1 = cz*sy*sx - cx*sz; + result.m2 = sz*sx + cz*cx*sy; + result.m3 = 0; + + result.m4 = cy*sz; + result.m5 = cz*cx + sz*sy*sx; + result.m6 = cx*sz*sy - cz*sx; + result.m7 = 0; + + result.m8 = -sy; + result.m9 = cy*sx; + result.m10 = cy*cx; + result.m11 = 0; + + result.m12 = 0; + result.m13 = 0; + result.m14 = 0; + result.m15 = 1; + + return result; +} + +// Returns scaling matrix +RMDEF Matrix MatrixScale(float x, float y, float z) +{ + Matrix result = { x, 0.0f, 0.0f, 0.0f, + 0.0f, y, 0.0f, 0.0f, + 0.0f, 0.0f, z, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f }; return result; } @@ -987,27 +1097,24 @@ RMDEF Matrix MatrixLookAt(Vector3 eye, Vector3 target, Vector3 up) Vector3 x = Vector3CrossProduct(up, z); x = Vector3Normalize(x); Vector3 y = Vector3CrossProduct(z, x); - y = Vector3Normalize(y); result.m0 = x.x; - result.m1 = x.y; - result.m2 = x.z; + result.m1 = y.x; + result.m2 = z.x; result.m3 = 0.0f; - result.m4 = y.x; + result.m4 = x.y; result.m5 = y.y; - result.m6 = y.z; + result.m6 = z.y; result.m7 = 0.0f; - result.m8 = z.x; - result.m9 = z.y; + result.m8 = x.z; + result.m9 = y.z; result.m10 = z.z; result.m11 = 0.0f; - result.m12 = eye.x; - result.m13 = eye.y; - result.m14 = eye.z; + result.m12 = -Vector3DotProduct(x, eye); + result.m13 = -Vector3DotProduct(y, eye); + result.m14 = -Vector3DotProduct(z, eye); result.m15 = 1.0f; - result = MatrixInvert(result); - return result; } @@ -1040,6 +1147,34 @@ RMDEF float16 MatrixToFloatV(Matrix mat) // Module Functions Definition - Quaternion math //---------------------------------------------------------------------------------- +// Add two quaternions +RMDEF Quaternion QuaternionAdd(Quaternion q1, Quaternion q2) +{ + Quaternion result = {q1.x + q2.x, q1.y + q2.y, q1.z + q2.z, q1.w + q2.w}; + return result; +} + +// Add quaternion and float value +RMDEF Quaternion QuaternionAddValue(Quaternion q, float add) +{ + Quaternion result = {q.x + add, q.y + add, q.z + add, q.w + add}; + return result; +} + +// Subtract two quaternions +RMDEF Quaternion QuaternionSubtract(Quaternion q1, Quaternion q2) +{ + Quaternion result = {q1.x - q2.x, q1.y - q2.y, q1.z - q2.z, q1.w - q2.w}; + return result; +} + +// Subtract quaternion and float value +RMDEF Quaternion QuaternionSubtractValue(Quaternion q, float sub) +{ + Quaternion result = {q.x - sub, q.y - sub, q.z - sub, q.w - sub}; + return result; +} + // Returns identity quaternion RMDEF Quaternion QuaternionIdentity(void) { @@ -1050,7 +1185,7 @@ RMDEF Quaternion QuaternionIdentity(void) // Computes the length of a quaternion RMDEF float QuaternionLength(Quaternion q) { - float result = (float)sqrt(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); + float result = sqrtf(q.x*q.x + q.y*q.y + q.z*q.z + q.w*q.w); return result; } @@ -1108,6 +1243,28 @@ RMDEF Quaternion QuaternionMultiply(Quaternion q1, Quaternion q2) return result; } +// Scale quaternion by float value +RMDEF Quaternion QuaternionScale(Quaternion q, float mul) +{ + Quaternion result = { 0 }; + + float qax = q.x, qay = q.y, qaz = q.z, qaw = q.w; + + result.x = qax*mul + qaw*mul + qay*mul - qaz*mul; + result.y = qay*mul + qaw*mul + qaz*mul - qax*mul; + result.z = qaz*mul + qaw*mul + qax*mul - qay*mul; + result.w = qaw*mul - qax*mul - qay*mul - qaz*mul; + + return result; +} + +// Divide two quaternions +RMDEF Quaternion QuaternionDivide(Quaternion q1, Quaternion q2) +{ + Quaternion result = { q1.x/q2.x, q1.y/q2.y, q1.z/q2.z, q1.w/q2.w }; + return result; +} + // Calculate linear interpolation between two quaternions RMDEF Quaternion QuaternionLerp(Quaternion q1, Quaternion q2, float amount) { @@ -1137,6 +1294,12 @@ RMDEF Quaternion QuaternionSlerp(Quaternion q1, Quaternion q2, float amount) float cosHalfTheta = q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w; + if (cosHalfTheta < 0) + { + q2.x = -q2.x; q2.y = -q2.y; q2.z = -q2.z; q2.w = -q2.w; + cosHalfTheta = -cosHalfTheta; + } + if (fabs(cosHalfTheta) >= 1.0f) result = q1; else if (cosHalfTheta > 0.95f) result = QuaternionNlerp(q1, q2, amount); else @@ -1176,7 +1339,7 @@ RMDEF Quaternion QuaternionFromVector3ToVector3(Vector3 from, Vector3 to) result.x = cross.x; result.y = cross.y; - result.z = cross.y; + result.z = cross.z; result.w = 1.0f + cos2Theta; // NOTE: Added QuaternioIdentity() // Normalize to essentially nlerp the original and identity to 0.5 @@ -1193,52 +1356,30 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix mat) { Quaternion result = { 0 }; - float trace = MatrixTrace(mat); - - if (trace > 0.0f) + if ((mat.m0 > mat.m5) && (mat.m0 > mat.m10)) { - float s = sqrtf(trace + 1)*2.0f; - float invS = 1.0f/s; + float s = sqrtf(1.0f + mat.m0 - mat.m5 - mat.m10)*2; - result.w = s*0.25f; - result.x = (mat.m6 - mat.m9)*invS; - result.y = (mat.m8 - mat.m2)*invS; - result.z = (mat.m1 - mat.m4)*invS; + result.x = 0.25f*s; + result.y = (mat.m4 + mat.m1)/s; + result.z = (mat.m2 + mat.m8)/s; + result.w = (mat.m9 - mat.m6)/s; + } + else if (mat.m5 > mat.m10) + { + float s = sqrtf(1.0f + mat.m5 - mat.m0 - mat.m10)*2; + result.x = (mat.m4 + mat.m1)/s; + result.y = 0.25f*s; + result.z = (mat.m9 + mat.m6)/s; + result.w = (mat.m2 - mat.m8)/s; } else { - float m00 = mat.m0, m11 = mat.m5, m22 = mat.m10; - - if (m00 > m11 && m00 > m22) - { - float s = (float)sqrt(1.0f + m00 - m11 - m22)*2.0f; - float invS = 1.0f/s; - - result.w = (mat.m6 - mat.m9)*invS; - result.x = s*0.25f; - result.y = (mat.m4 + mat.m1)*invS; - result.z = (mat.m8 + mat.m2)*invS; - } - else if (m11 > m22) - { - float s = sqrtf(1.0f + m11 - m00 - m22)*2.0f; - float invS = 1.0f/s; - - result.w = (mat.m8 - mat.m2)*invS; - result.x = (mat.m4 + mat.m1)*invS; - result.y = s*0.25f; - result.z = (mat.m9 + mat.m6)*invS; - } - else - { - float s = sqrtf(1.0f + m22 - m00 - m11)*2.0f; - float invS = 1.0f/s; - - result.w = (mat.m1 - mat.m4)*invS; - result.x = (mat.m8 + mat.m2)*invS; - result.y = (mat.m9 + mat.m6)*invS; - result.z = s*0.25f; - } + float s = sqrtf(1.0f + mat.m10 - mat.m0 - mat.m5)*2; + result.x = (mat.m2 + mat.m8)/s; + result.y = (mat.m9 + mat.m6)/s; + result.z = 0.25f*s; + result.w = (mat.m4 - mat.m1)/s; } return result; @@ -1247,45 +1388,24 @@ RMDEF Quaternion QuaternionFromMatrix(Matrix mat) // Returns a matrix for a given quaternion RMDEF Matrix QuaternionToMatrix(Quaternion q) { - Matrix result = { 0 }; - - float x = q.x, y = q.y, z = q.z, w = q.w; - - float x2 = x + x; - float y2 = y + y; - float z2 = z + z; + Matrix result = MatrixIdentity(); - float length = QuaternionLength(q); - float lengthSquared = length*length; + float a2 = 2*(q.x*q.x), b2=2*(q.y*q.y), c2=2*(q.z*q.z); //, d2=2*(q.w*q.w); - float xx = x*x2/lengthSquared; - float xy = x*y2/lengthSquared; - float xz = x*z2/lengthSquared; + float ab = 2*(q.x*q.y), ac=2*(q.x*q.z), bc=2*(q.y*q.z); + float ad = 2*(q.x*q.w), bd=2*(q.y*q.w), cd=2*(q.z*q.w); - float yy = y*y2/lengthSquared; - float yz = y*z2/lengthSquared; - float zz = z*z2/lengthSquared; + result.m0 = 1 - b2 - c2; + result.m1 = ab - cd; + result.m2 = ac + bd; - float wx = w*x2/lengthSquared; - float wy = w*y2/lengthSquared; - float wz = w*z2/lengthSquared; + result.m4 = ab + cd; + result.m5 = 1 - a2 - c2; + result.m6 = bc - ad; - result.m0 = 1.0f - (yy + zz); - result.m1 = xy - wz; - result.m2 = xz + wy; - result.m3 = 0.0f; - result.m4 = xy + wz; - result.m5 = 1.0f - (xx + zz); - result.m6 = yz - wx; - result.m7 = 0.0f; - result.m8 = xz - wy; - result.m9 = yz + wx; - result.m10 = 1.0f - (xx + yy); - result.m11 = 0.0f; - result.m12 = 0.0f; - result.m13 = 0.0f; - result.m14 = 0.0f; - result.m15 = 1.0f; + result.m8 = ac - bd; + result.m9 = bc + ad; + result.m10 = 1 - a2 - b2; return result; } @@ -1341,17 +1461,18 @@ RMDEF void QuaternionToAxisAngle(Quaternion q, Vector3 *outAxis, float *outAngle *outAngle = resAngle; } -// Returns he quaternion equivalent to Euler angles -RMDEF Quaternion QuaternionFromEuler(float roll, float pitch, float yaw) +// Returns the quaternion equivalent to Euler angles +// NOTE: Rotation order is ZYX +RMDEF Quaternion QuaternionFromEuler(float pitch, float yaw, float roll) { Quaternion q = { 0 }; - float x0 = cosf(roll*0.5f); - float x1 = sinf(roll*0.5f); - float y0 = cosf(pitch*0.5f); - float y1 = sinf(pitch*0.5f); - float z0 = cosf(yaw*0.5f); - float z1 = sinf(yaw*0.5f); + float x0 = cosf(pitch*0.5f); + float x1 = sinf(pitch*0.5f); + float y0 = cosf(yaw*0.5f); + float y1 = sinf(yaw*0.5f); + float z0 = cosf(roll*0.5f); + float z1 = sinf(roll*0.5f); q.x = x1*y0*z0 - x0*y1*z1; q.y = x0*y1*z0 + x1*y0*z1; @@ -1399,4 +1520,27 @@ RMDEF Quaternion QuaternionTransform(Quaternion q, Matrix mat) return result; } +// Projects a Vector3 from screen space into object space +RMDEF Vector3 Vector3Unproject(Vector3 source, Matrix projection, Matrix view) +{ + Vector3 result = { 0.0f, 0.0f, 0.0f }; + + // Calculate unproject matrix (multiply view patrix by projection matrix) and invert it + Matrix matViewProj = MatrixMultiply(view, projection); + matViewProj = MatrixInvert(matViewProj); + + // Create quaternion from source point + Quaternion quat = { source.x, source.y, source.z, 1.0f }; + + // Multiply quat point by unproject matrix + quat = QuaternionTransform(quat, matViewProj); + + // Normalized world points in vectors + result.x = quat.x/quat.w; + result.y = quat.y/quat.w; + result.z = quat.z/quat.w; + + return result; +} + #endif // RAYMATH_H |