summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--API.md204
-rw-r--r--README.md5
-rw-r--r--devnotes3
-rw-r--r--include/lua_core.h1
-rw-r--r--include/rmath.h23
-rw-r--r--src/lua_core.c35
-rw-r--r--src/rmath.c500
7 files changed, 765 insertions, 6 deletions
diff --git a/API.md b/API.md
index 8861466..1773b14 100644
--- a/API.md
+++ b/API.md
@@ -4071,6 +4071,210 @@ Get camera look-at matrix ( View matrix )
---
+## Math - Quaternion
+
+---
+
+> result = RL_QuaternionAdd( Quaternion q1, Quaternion q2 )
+
+Add two quaternions
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionAddValue( Quaternion q, float add )
+
+Add quaternion and float value
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionSubtract( Quaternion q1, Quaternion q2 )
+
+Subtract two quaternions
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionSubtractValue( Quaternion q, float sub )
+
+Subtract quaternion and float value
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionIdentity()
+
+Get identity quaternion
+
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionLength( Quaternion q )
+
+Computes the length of a quaternion
+
+- Failure return false
+- Success return float
+
+---
+
+> result = RL_QuaternionNormalize( Quaternion q )
+
+Normalize provided quaternion
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionInvert( Quaternion q )
+
+Invert provided quaternion
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionMultiply( Quaternion q1, Quaternion q2 )
+
+Calculate two quaternion multiplication
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionScale( Quaternion q, float mul )
+
+Scale quaternion by float value
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionDivide( Quaternion q1, Quaternion q2 )
+
+Divide two quaternions
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionLerp( Quaternion q1, Quaternion q2, float amount )
+
+Calculate linear interpolation between two quaternions
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionNlerp( Quaternion q1, Quaternion q2, float amount )
+
+Calculate slerp-optimized interpolation between two quaternions
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionSlerp( Quaternion q1, Quaternion q2, float amount )
+
+Calculates spherical linear interpolation between two quaternions
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionFromVector3ToVector3( Vector3 from, Vector3 to )
+
+Calculate quaternion based on the rotation from one vector to another
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionFromMatrix( Matrix mat )
+
+Get a quaternion for a given rotation matrix
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionToMatrix( Quaternion q )
+
+Get a quaternion for a given rotation matrix
+
+- Failure return false
+- Success return Matrix
+
+---
+
+> result = RL_QuaternionFromAxisAngle( Vector3 axis, float angle )
+
+Get rotation quaternion for an angle and axis
+NOTE: angle must be provided in radians
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> axis, angle = RL_QuaternionToAxisAngle( Quaternion q )
+
+Get the rotation angle and axis for a given quaternion
+
+- Failure return false
+- Success return Vector3, float
+
+---
+
+> result = RL_QuaternionFromEuler( float pitch, float yaw, float roll )
+
+Get the quaternion equivalent to Euler angles
+NOTE: Rotation order is ZYX
+
+- Failure return false
+- Success return Quaternion
+
+---
+
+> result = RL_QuaternionToEuler( Quaternion q )
+
+Get the Euler angles equivalent to quaternion (roll, pitch, yaw)
+NOTE: Angles are returned in a Vector3 struct in radians
+
+- Failure return false
+- Success return Vector3
+
+---
+
+> result = RL_QuaternionTransform( Quaternion q, Matrix mat )
+
+Transform a quaternion given a transformation matrix
+
+- Failure return false
+- Success return Quaternion
+
+---
+
## Gui - Global
---
diff --git a/README.md b/README.md
index a4b2788..54bde93 100644
--- a/README.md
+++ b/README.md
@@ -29,10 +29,7 @@ List of some MISSING features that are planned to be included. For specific func
Submodules.
* Raygui ( Done )
-* Raymath
- * Quaternions
-* Physac
- * Whole implementation
+* Raymath ( Mostly done )
## Usage
diff --git a/devnotes b/devnotes
index 8109151..b7d1d2d 100644
--- a/devnotes
+++ b/devnotes
@@ -12,8 +12,7 @@ Backlog {
* Wave
* Raymath
- * Quaternions
- * Physac
+ * Physac?
* VR?
}
diff --git a/include/lua_core.h b/include/lua_core.h
index 335ee49..2cd120e 100644
--- a/include/lua_core.h
+++ b/include/lua_core.h
@@ -23,6 +23,7 @@ void uluaPushVector2( lua_State *L, Vector2 vector );
void uluaPushVector3( lua_State *L, Vector3 vector );
void uluaPushVector4( lua_State *L, Vector4 vector );
void uluaPushRectangle( lua_State *L, Rectangle rect );
+void uluaPushQuaternion( lua_State *L, Quaternion quaternion );
void uluaPushMatrix( lua_State *L, Matrix matrix );
void uluaPushRay( lua_State *L, Ray ray );
void uluaPushRayCollision( lua_State *L, RayCollision rayCol );
diff --git a/include/rmath.h b/include/rmath.h
index b43db8b..b3d7965 100644
--- a/include/rmath.h
+++ b/include/rmath.h
@@ -48,3 +48,26 @@ int lmathMatrixFrustum( lua_State *L );
int lmathMatrixPerspective( lua_State *L );
int lmathMatrixOrtho( lua_State *L );
int lmathMatrixLookAt( lua_State *L );
+/* Quaternion. */
+int lmathQuaternionAdd( lua_State *L );
+int lmathQuaternionAddValue( lua_State *L );
+int lmathQuaternionSubtract( lua_State *L );
+int lmathQuaternionSubtractValue( lua_State *L );
+int lmathQuaternionIdentity( lua_State *L );
+int lmathQuaternionLength( lua_State *L );
+int lmathQuaternionNormalize( lua_State *L );
+int lmathQuaternionInvert( lua_State *L );
+int lmathQuaternionMultiply( lua_State *L );
+int lmathQuaternionScale( lua_State *L );
+int lmathQuaternionDivide( lua_State *L );
+int lmathQuaternionLerp( lua_State *L );
+int lmathQuaternionNlerp( lua_State *L );
+int lmathQuaternionSlerp( lua_State *L );
+int lmathQuaternionFromVector3ToVector3( lua_State *L );
+int lmathQuaternionFromMatrix( lua_State *L );
+int lmathQuaternionToMatrix( lua_State *L );
+int lmathQuaternionFromAxisAngle( lua_State *L );
+int lmathQuaternionToAxisAngle( lua_State *L );
+int lmathQuaternionFromEuler( lua_State *L );
+int lmathQuaternionToEuler( lua_State *L );
+int lmathQuaternionTransform( lua_State *L );
diff --git a/src/lua_core.c b/src/lua_core.c
index 60b07f9..cddad38 100644
--- a/src/lua_core.c
+++ b/src/lua_core.c
@@ -888,6 +888,29 @@ void luaRegister() {
lua_register( L, "RL_MatrixPerspective", lmathMatrixPerspective );
lua_register( L, "RL_MatrixOrtho", lmathMatrixOrtho );
lua_register( L, "RL_MatrixLookAt", lmathMatrixLookAt );
+ /* Quaternion. */
+ lua_register( L, "RL_QuaternionAdd", lmathQuaternionAdd );
+ lua_register( L, "RL_QuaternionAddValue", lmathQuaternionAddValue );
+ lua_register( L, "RL_QuaternionSubtract", lmathQuaternionSubtract );
+ lua_register( L, "RL_QuaternionSubtractValue", lmathQuaternionSubtractValue );
+ lua_register( L, "RL_QuaternionIdentity", lmathQuaternionIdentity );
+ lua_register( L, "RL_QuaternionLength", lmathQuaternionLength );
+ lua_register( L, "RL_QuaternionNormalize", lmathQuaternionNormalize );
+ lua_register( L, "RL_QuaternionInvert", lmathQuaternionInvert );
+ lua_register( L, "RL_QuaternionMultiply", lmathQuaternionMultiply );
+ lua_register( L, "RL_QuaternionScale", lmathQuaternionScale );
+ lua_register( L, "RL_QuaternionDivide", lmathQuaternionDivide );
+ lua_register( L, "RL_QuaternionLerp", lmathQuaternionLerp );
+ lua_register( L, "RL_QuaternionNlerp", lmathQuaternionNlerp );
+ lua_register( L, "RL_QuaternionSlerp", lmathQuaternionSlerp );
+ lua_register( L, "RL_QuaternionFromVector3ToVector3", lmathQuaternionFromVector3ToVector3 );
+ lua_register( L, "RL_QuaternionFromMatrix", lmathQuaternionFromMatrix );
+ lua_register( L, "RL_QuaternionToMatrix", lmathQuaternionToMatrix );
+ lua_register( L, "RL_QuaternionFromAxisAngle", lmathQuaternionFromAxisAngle );
+ lua_register( L, "RL_QuaternionToAxisAngle", lmathQuaternionToAxisAngle );
+ lua_register( L, "RL_QuaternionFromEuler", lmathQuaternionFromEuler );
+ lua_register( L, "RL_QuaternionToEuler", lmathQuaternionToEuler );
+ lua_register( L, "RL_QuaternionTransform", lmathQuaternionTransform );
/* Gui. */
/* Global. */
@@ -1346,6 +1369,18 @@ void uluaPushRectangle( lua_State *L, Rectangle rect ) {
lua_rawseti( L, -2, 4 );
}
+void uluaPushQuaternion( lua_State *L, Quaternion quaternion ) {
+ lua_createtable( L, 4, 0 );
+ lua_pushnumber( L, quaternion.x );
+ lua_rawseti( L, -2, 1 );
+ lua_pushnumber( L, quaternion.y );
+ lua_rawseti( L, -2, 2 );
+ lua_pushnumber( L, quaternion.z );
+ lua_rawseti( L, -2, 3 );
+ lua_pushnumber( L, quaternion.w );
+ lua_rawseti( L, -2, 4 );
+}
+
void uluaPushMatrix( lua_State *L, Matrix matrix ) {
lua_createtable( L, 4, 0 );
diff --git a/src/rmath.c b/src/rmath.c
index b003b65..a750089 100644
--- a/src/rmath.c
+++ b/src/rmath.c
@@ -976,3 +976,503 @@ int lmathMatrixLookAt( lua_State *L ) {
return 1;
}
+
+/*
+## Math - Quaternion
+*/
+
+/*
+> result = RL_QuaternionAdd( Quaternion q1, Quaternion q2 )
+
+Add two quaternions
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionAdd( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionAdd( Quaternion q1, Quaternion q2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q2 = uluaGetQuaternion( L );
+ lua_pop( L, 1 );
+ Quaternion q1 = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionAdd( q1, q2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionAddValue( Quaternion q, float add )
+
+Add quaternion and float value
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionAddValue( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionAddValue( Quaternion q, float add )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float add = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionAddValue( q, add ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionSubtract( Quaternion q1, Quaternion q2 )
+
+Subtract two quaternions
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionSubtract( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionSubtract( Quaternion q1, Quaternion q2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q2 = uluaGetQuaternion( L );
+ lua_pop( L, 1 );
+ Quaternion q1 = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionSubtract( q1, q2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionSubtractValue( Quaternion q, float sub )
+
+Subtract quaternion and float value
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionSubtractValue( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionSubtractValue( Quaternion q, float sub )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float sub = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionSubtractValue( q, sub ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionIdentity()
+
+Get identity quaternion
+
+- Success return Quaternion
+*/
+int lmathQuaternionIdentity( lua_State *L ) {
+ uluaPushQuaternion( L, QuaternionIdentity() );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionLength( Quaternion q )
+
+Computes the length of a quaternion
+
+- Failure return false
+- Success return float
+*/
+int lmathQuaternionLength( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionLength( Quaternion q )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q = uluaGetQuaternion( L );
+
+ lua_pushnumber( L, QuaternionLength( q ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionNormalize( Quaternion q )
+
+Normalize provided quaternion
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionNormalize( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionNormalize( Quaternion q )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionNormalize( q ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionInvert( Quaternion q )
+
+Invert provided quaternion
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionInvert( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionInvert( Quaternion q )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionInvert( q ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionMultiply( Quaternion q1, Quaternion q2 )
+
+Calculate two quaternion multiplication
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionMultiply( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionMultiply( Quaternion q1, Quaternion q2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q2 = uluaGetQuaternion( L );
+ lua_pop( L, 1 );
+ Quaternion q1 = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionMultiply( q1, q2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionScale( Quaternion q, float mul )
+
+Scale quaternion by float value
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionScale( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionScale( Quaternion q, float mul )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float mul = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionScale( q, mul ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionDivide( Quaternion q1, Quaternion q2 )
+
+Divide two quaternions
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionDivide( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionDivide( Quaternion q1, Quaternion q2 )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q2 = uluaGetQuaternion( L );
+ lua_pop( L, 1 );
+ Quaternion q1 = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionDivide( q1, q2 ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionLerp( Quaternion q1, Quaternion q2, float amount )
+
+Calculate linear interpolation between two quaternions
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionLerp( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionLerp( Quaternion q1, Quaternion q2, float amount )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float amount = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Quaternion q2 = uluaGetQuaternion( L );
+ lua_pop( L, 1 );
+ Quaternion q1 = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionLerp( q1, q2, amount ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionNlerp( Quaternion q1, Quaternion q2, float amount )
+
+Calculate slerp-optimized interpolation between two quaternions
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionNlerp( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionNlerp( Quaternion q1, Quaternion q2, float amount )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float amount = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Quaternion q2 = uluaGetQuaternion( L );
+ lua_pop( L, 1 );
+ Quaternion q1 = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionNlerp( q1, q2, amount ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionSlerp( Quaternion q1, Quaternion q2, float amount )
+
+Calculates spherical linear interpolation between two quaternions
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionSlerp( lua_State *L ) {
+ if ( !lua_istable( L, -3 ) || !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionSlerp( Quaternion q1, Quaternion q2, float amount )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float amount = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Quaternion q2 = uluaGetQuaternion( L );
+ lua_pop( L, 1 );
+ Quaternion q1 = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionSlerp( q1, q2, amount ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionFromVector3ToVector3( Vector3 from, Vector3 to )
+
+Calculate quaternion based on the rotation from one vector to another
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionFromVector3ToVector3( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionFromVector3ToVector3( Vector3 from, Vector3 to )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Vector3 to = uluaGetVector3( L );
+ lua_pop( L, 1 );
+ Vector3 from = uluaGetVector3( L );
+
+ uluaPushQuaternion( L, QuaternionFromVector3ToVector3( from, to ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionFromMatrix( Matrix mat )
+
+Get a quaternion for a given rotation matrix
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionFromMatrix( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionFromMatrix( Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat = uluaGetMatrix( L );
+
+ uluaPushQuaternion( L, QuaternionFromMatrix( mat ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionToMatrix( Quaternion q )
+
+Get a quaternion for a given rotation matrix
+
+- Failure return false
+- Success return Matrix
+*/
+int lmathQuaternionToMatrix( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionToMatrix( Quaternion q )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushMatrix( L, QuaternionToMatrix( q ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionFromAxisAngle( Vector3 axis, float angle )
+
+Get rotation quaternion for an angle and axis
+NOTE: angle must be provided in radians
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionFromAxisAngle( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionFromAxisAngle( Vector3 axis, float angle )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float angle = lua_tonumber( L, -1 );
+ lua_pop( L, 1 );
+ Vector3 axis = uluaGetVector3( L );
+
+ uluaPushQuaternion( L, QuaternionFromAxisAngle( axis, angle ) );
+
+ return 1;
+}
+
+/*
+> axis, angle = RL_QuaternionToAxisAngle( Quaternion q )
+
+Get the rotation angle and axis for a given quaternion
+
+- Failure return false
+- Success return Vector3, float
+*/
+int lmathQuaternionToAxisAngle( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionToAxisAngle( Quaternion q )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q = uluaGetQuaternion( L );
+ float angle = 0.0;
+ Vector3 axis = { 0.0 };
+
+ QuaternionToAxisAngle( q, &axis, &angle );
+
+ uluaPushVector3( L, axis );
+ lua_pushnumber( L, angle );
+
+ return 2;
+}
+
+/*
+> result = RL_QuaternionFromEuler( float pitch, float yaw, float roll )
+
+Get the quaternion equivalent to Euler angles
+NOTE: Rotation order is ZYX
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionFromEuler( lua_State *L ) {
+ if ( !lua_isnumber( L, -3 ) || !lua_isnumber( L, -2 ) || !lua_isnumber( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionFromEuler( float pitch, float yaw, float roll )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ float roll = lua_tonumber( L, -1 );
+ float yaw = lua_tonumber( L, -2 );
+ float pitch = lua_tonumber( L, -3 );
+
+ uluaPushQuaternion( L, QuaternionFromEuler( pitch, yaw, roll ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionToEuler( Quaternion q )
+
+Get the Euler angles equivalent to quaternion (roll, pitch, yaw)
+NOTE: Angles are returned in a Vector3 struct in radians
+
+- Failure return false
+- Success return Vector3
+*/
+int lmathQuaternionToEuler( lua_State *L ) {
+ if ( !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionToEuler( Quaternion q )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushVector3( L, QuaternionToEuler( q ) );
+
+ return 1;
+}
+
+/*
+> result = RL_QuaternionTransform( Quaternion q, Matrix mat )
+
+Transform a quaternion given a transformation matrix
+
+- Failure return false
+- Success return Quaternion
+*/
+int lmathQuaternionTransform( lua_State *L ) {
+ if ( !lua_istable( L, -2 ) || !lua_istable( L, -1 ) ) {
+ TraceLog( LOG_WARNING, "%s", "Bad call of function. RL_QuaternionTransform( Quaternion q, Matrix mat )" );
+ lua_pushboolean( L, false );
+ return 1;
+ }
+ Matrix mat = uluaGetMatrix( L );
+ lua_pop( L, 1 );
+ Quaternion q = uluaGetQuaternion( L );
+
+ uluaPushQuaternion( L, QuaternionTransform( q, mat ) );
+
+ return 1;
+}