CubicSDR/external/cubicvr2/math/quaternion.h

101 lines
3.7 KiB
C++

//
// quaternion.h
// CubicVR2
//
// Created by Charles J. Cliffe on 2013-02-22.
// Copyright (c) 2013 Charles J. Cliffe. All rights reserved.
//
#ifndef __CubicVR2__quaternion__
#define __CubicVR2__quaternion__
#include <iostream>
#include "vec4.h"
#include "mat4.h"
namespace CubicVR {
struct quaternion : vec4 {
static vec4 fromMatrix(mat4 mat) {
__float t = 1 + mat[0] + mat[5] + mat[10];
__float S,X,Y,Z,W;
if ( t > 0.00000001 ) {
S = sqrtf(t) * 2;
X = ( mat[9] - mat[6] ) / S;
Y = ( mat[2] - mat[8] ) / S;
Z = ( mat[4] - mat[1] ) / S;
W = 0.25f * S;
} else {
if ( mat[0] > mat[5] && mat[0] > mat[10] ) { // Column 0:
S = sqrtf( 1.0f + mat[0] - mat[5] - mat[10] ) * 2.0f;
X = 0.25f * S;
Y = (mat[4] + mat[1] ) / S;
Z = (mat[2] + mat[8] ) / S;
W = (mat[9] - mat[6] ) / S;
} else if ( mat[5] > mat[10] ) { // Column 1:
S = sqrtf( 1.0f + mat[5] - mat[0] - mat[10] ) * 2.0f;
X = (mat[4] + mat[1] ) / S;
Y = 0.25f * S;
Z = (mat[9] + mat[6] ) / S;
W = (mat[2] - mat[8] ) / S;
} else { // Column 2:
S = sqrtf( 1.0f + mat[10] - mat[0] - mat[5] ) * 2.0f;
X = (mat[2] + mat[8] ) / S;
Y = (mat[9] + mat[6] ) / S;
Z = 0.25f * S;
W = (mat[4] - mat[1] ) / S;
}
}
return vec4(X,Y,Z,W);
};
static vec4 fromEuler(__float bank, __float heading, __float pitch) { // x,y,z
__float c1 = cosf(((float)M_PI / 180.0f) * heading / 2.0f);
__float s1 = sinf(((float)M_PI / 180.0f) * heading / 2.0f);
__float c2 = cosf(((float)M_PI / 180.0f) * pitch / 2.0f);
__float s2 = sinf(((float)M_PI / 180.0f) * pitch / 2.0f);
__float c3 = cosf(((float)M_PI / 180.0f) * bank / 2.0f);
__float s3 = sinf(((float)M_PI / 180.0f) * bank / 2.0f);
__float c1c2 = c1 * c2;
__float s1s2 = s1 * s2;
vec4 mOut;
mOut[0] = c1c2 * c3 - s1s2 * s3;
mOut[1] = c1c2 * s3 + s1s2 * c3;
mOut[2] = s1 * c2 * c3 + c1 * s2 * s3;
mOut[3] = c1 * s2 * c3 - s1 * c2 * s3;
return mOut;
};
static vec3 toEuler(vec4 q) {
__float sqx = q[0] * q[0];
__float sqy = q[1] * q[1];
__float sqz = q[2] * q[2];
__float sqw = q[3] * q[3];
__float x = (180.0f / (float)M_PI) * ((atan2f(2.0f * (q[1] * q[2] + q[0] * q[3]), (-sqx - sqy + sqz + sqw))));
__float y = (180.0f / (float)M_PI) * ((asinf(-2.0f * (q[0] * q[2] - q[1] * q[3]))));
__float z = (180.0f / (float)M_PI) * ((atan2f(2.0f * (q[0] * q[1] + q[2] * q[3]), (sqx - sqy - sqz + sqw))));
return vec3(x, y, z);
};
static vec4 multiply(vec4 q1, vec4 q2) {
__float x = q1[0] * q2[3] + q1[3] * q2[0] + q1[1] * q2[2] - q1[2] * q2[1];
__float y = q1[1] * q2[3] + q1[3] * q2[1] + q1[2] * q2[0] - q1[0] * q2[2];
__float z = q1[2] * q2[3] + q1[3] * q2[2] + q1[0] * q2[1] - q1[1] * q2[0];
__float w = q1[3] * q2[3] - q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2];
return vec4(x,y,z,w);
};
};
}
#endif /* defined(__CubicVR2__quaternion__) */