This commit is contained in:
Thompson Lee 2016-08-11 16:19:36 +00:00 committed by GitHub
commit 9b7a2d2c1f
3 changed files with 46 additions and 4 deletions

View File

@ -573,7 +573,7 @@ C3D_FQuat Quat_Pow(C3D_FQuat q, float p);
* @brief Cross product of Quaternion and FVec3 * @brief Cross product of Quaternion and FVec3
* @param[in] lhs Left-side Quaternion * @param[in] lhs Left-side Quaternion
* @param[in] rhs Right-side FVec3 * @param[in] rhs Right-side FVec3
* @return q×v * @return q × v
*/ */
C3D_FVec Quat_CrossFVec3(C3D_FQuat q, C3D_FVec v); C3D_FVec Quat_CrossFVec3(C3D_FQuat q, C3D_FVec v);
@ -651,7 +651,7 @@ static inline C3D_FQuat Quat_Conjugate(C3D_FQuat q)
static inline C3D_FQuat Quat_Inverse(C3D_FQuat q) static inline C3D_FQuat Quat_Inverse(C3D_FQuat q)
{ {
// q^-1 = (q.r - q.i - q.j - q.k) / (q.r^2 + q.i^2 + q.j^2 + q.k^2) // q^-1 = (q.r - q.i - q.j - q.k) / (q.r^2 + q.i^2 + q.j^2 + q.k^2)
// = q* / (qq) // = q* / (q · q)
C3D_FQuat c = Quat_Conjugate(q); C3D_FQuat c = Quat_Conjugate(q);
float d = Quat_Dot(q, q); float d = Quat_Dot(q, q);
return Quat_New(c.i/d, c.j/d, c.k/d, c.r/d); return Quat_New(c.i/d, c.j/d, c.k/d, c.r/d);
@ -661,11 +661,29 @@ static inline C3D_FQuat Quat_Inverse(C3D_FQuat q)
* @brief Cross product of FVec3 and Quaternion * @brief Cross product of FVec3 and Quaternion
* @param[in] lhs Left-side FVec3 * @param[in] lhs Left-side FVec3
* @param[in] rhs Right-side Quaternion * @param[in] rhs Right-side Quaternion
* @return v×q * @return v × q
*/ */
static inline C3D_FVec FVec3_CrossQuat(C3D_FVec v, C3D_FQuat q) static inline C3D_FVec FVec3_CrossQuat(C3D_FVec v, C3D_FQuat q)
{ {
// v×q = q^-1×v // v × q = q^-1 × v
return Quat_CrossFVec3(Quat_Inverse(q), v); return Quat_CrossFVec3(Quat_Inverse(q), v);
} }
/**
* @brief Quaternion Look At
* @param[in] source C3D_FVec Starting position. Origin of rotation.
* @param[in] target C3D_FVec Target position to orient towards.
* @param[in] forwardVector C3D_FVec The Up vector.
* @param[in] upVector C3D_FVec The Up vector.
* @return Quaternion rotation.
*/
C3D_FQuat Quat_LookAt(C3D_FVec source, C3D_FVec target, C3D_FVec forwardVector, C3D_FVec upVector);
/**
* @brief Quaternion, created from a given axis and angle in radians.
* @param[in] axis C3D_FVec The axis to rotate around at.
* @param[in] angle float The angle to rotate. Unit: Radians
* @return Quaternion rotation based on the axis and angle. Axis doesn't have to be orthogonal.
*/
C3D_FQuat Quat_FromAxisAngle(C3D_FVec axis, float angle);
///@} ///@}

View File

@ -0,0 +1,9 @@
#include <c3d/maths.h>
C3D_FQuat Quat_FromAxisAngle(C3D_FVec axis, float angle)
{
float halfAngle = angle / 2.0f;
float scale = sinf(halfAngle);
axis = Quat_Normalize(axis);
return Quat_New(axis.x * scale, axis.y * scale, axis.z * scale, cosf(halfAngle));
}

View File

@ -0,0 +1,15 @@
#include <c3d/maths.h>
#include <float.h>
C3D_FQuat Quat_LookAt(C3D_FVec source, C3D_FVec target, C3D_FVec forwardVector, C3D_FVec upVector)
{
C3D_FVec forward = FVec3_Normalize(FVec3_Subtract(target, source));
float dot = FVec3_Dot(forwardVector, forward);
if (dot + 1.0f < FLT_EPSILON)
return Quat_FromAxisAngle(upVector, M_TAU/2.0f);
if (dot - 1.0f < -FLT_EPSILON)
return Quat_Identity();
float rotationAngle = acosf(dot);
C3D_FVec rotationAxis = FVec3_Cross(forwardVector, forward);
return Quat_FromAxisAngle(rotationAxis, rotationAngle);
}