//============ Copyright (c) Valve Corporation, All rights reserved. ============ #pragma once #include "openvr_driver.h" #include #ifndef M_PI #define M_PI 3.1415926535 #endif #define DEG_TO_RAD( degrees ) ( ( degrees )*M_PI / 180.0 ) #define RAD_TO_DEG( radians ) ( ( radians )*180.0 / M_PI ) static const vr::HmdQuaternion_t HmdQuaternion_Identity = { 1.f, 0.f, 0.f, 0.f }; // right hand coordinate system static const vr::HmdVector3_t HmdVector3_Right = { 1.f, 0, 0 }; static const vr::HmdVector3_t HmdVector3_Left = { -1.f, 0, 0 }; static const vr::HmdVector3_t HmdVector3_Up = { 0, 1.f, 0 }; static const vr::HmdVector3_t HmdVector3_Down = { 0, -1.f, 0 }; static const vr::HmdVector3_t HmdVector3_Forward = { 0, 0, -1.f }; static const vr::HmdVector3_t HmdVector3_Backward = { 0, 0, 1.f }; // 3x3 or 3x4 matrix template < class T > vr::HmdQuaternion_t HmdQuaternion_FromMatrix( const T &matrix ) { vr::HmdQuaternion_t q{}; q.w = sqrt( fmax( 0, 1 + matrix.m[ 0 ][ 0 ] + matrix.m[ 1 ][ 1 ] + matrix.m[ 2 ][ 2 ] ) ) / 2; q.x = sqrt( fmax( 0, 1 + matrix.m[ 0 ][ 0 ] - matrix.m[ 1 ][ 1 ] - matrix.m[ 2 ][ 2 ] ) ) / 2; q.y = sqrt( fmax( 0, 1 - matrix.m[ 0 ][ 0 ] + matrix.m[ 1 ][ 1 ] - matrix.m[ 2 ][ 2 ] ) ) / 2; q.z = sqrt( fmax( 0, 1 - matrix.m[ 0 ][ 0 ] - matrix.m[ 1 ][ 1 ] + matrix.m[ 2 ][ 2 ] ) ) / 2; q.x = copysign( q.x, matrix.m[ 2 ][ 1 ] - matrix.m[ 1 ][ 2 ] ); q.y = copysign( q.y, matrix.m[ 0 ][ 2 ] - matrix.m[ 2 ][ 0 ] ); q.z = copysign( q.z, matrix.m[ 1 ][ 0 ] - matrix.m[ 0 ][ 1 ] ); return q; } static vr::HmdQuaternion_t HmdQuaternion_FromSwingTwist( const vr::HmdVector2_t &swing, const float twist ) { vr::HmdQuaternion_t result{}; const float swing_squared = swing.v[ 0 ] * swing.v[ 0 ] + swing.v[ 1 ] * swing.v[ 1 ]; if ( swing_squared > 0.f ) { const float theta_swing = std::sqrt( swing_squared ); const float cos_half_theta_swing = std::cos( theta_swing * 0.5f ); const float cos_half_theta_twist = std::cos( twist * 0.5f ); const float sin_half_theta_twist = std::sin( twist * 0.5f ); const float sin_half_theta_swing_over_theta = std::sin( theta_swing * 0.5f ) / theta_swing; result.w = cos_half_theta_swing * cos_half_theta_twist; result.x = cos_half_theta_swing * sin_half_theta_twist; result.y = ( swing.v[ 1 ] * cos_half_theta_twist * sin_half_theta_swing_over_theta ) - ( swing.v[ 0 ] * sin_half_theta_twist * sin_half_theta_swing_over_theta ); result.z = ( swing.v[ 0 ] * cos_half_theta_twist * sin_half_theta_swing_over_theta ) + ( swing.v[ 1 ] * sin_half_theta_twist * sin_half_theta_swing_over_theta ); } else { float half_twist = twist * 0.5f; float cos_half_twist = cos( half_twist ); float sin_half_twist = sin( half_twist ); float sin_half_theta_over_theta = 0.5f; result.w = cos_half_twist; result.x = sin_half_twist; result.y = ( swing.v[ 1 ] * cos_half_twist * sin_half_theta_over_theta ) - ( swing.v[ 0 ] * sin_half_twist * sin_half_theta_over_theta ); result.z = ( swing.v[ 0 ] * cos_half_twist * sin_half_theta_over_theta ) + ( swing.v[ 1 ] * sin_half_twist * sin_half_theta_over_theta ); } return result; } static vr::HmdQuaternion_t HmdQuaternion_Normalize( const vr::HmdQuaternion_t &q ) { vr::HmdQuaternion_t result{}; double n = sqrt( q.x * q.x + q.y * q.y + q.z * q.z + q.w * q.w ); result.w = q.w / n; result.x = q.x / n; result.y = q.y / n; result.z = q.z / n; return result; } static vr::HmdQuaternion_t HmdQuaternion_FromEulerAngles(double roll, double pitch, double yaw) { double cr = cos(roll * 0.5); double sr = sin(roll * 0.5); double cp = cos(pitch * 0.5); double sp = sin(pitch * 0.5); double cy = cos(yaw * 0.5); double sy = sin(yaw * 0.5); vr::HmdQuaternion_t q; q.w = cr * cp * cy + sr * sp * sy; q.x = cr * sp * cy + sr * cp * sy; q.y = cr * cp * sy - sr * sp * cy; q.z = sr * cp * cy - cr * sp * sy; return q; } template < class T, class Q > void HmdQuaternion_ConvertQuaternion( const T &in_quaternion, Q &out_quaternion ) { out_quaternion.w = in_quaternion.w; out_quaternion.x = in_quaternion.x; out_quaternion.y = in_quaternion.y; out_quaternion.z = in_quaternion.z; } static vr::HmdQuaternion_t operator-( const vr::HmdQuaternion_t &q ) { return { q.w, -q.x, -q.y, -q.z }; } static vr::HmdQuaternion_t operator*( const vr::HmdQuaternion_t &lhs, const vr::HmdQuaternion_t &rhs ) { return { lhs.w * rhs.w - lhs.x * rhs.x - lhs.y * rhs.y - lhs.z * rhs.z, lhs.w * rhs.x + lhs.x * rhs.w + lhs.y * rhs.z - lhs.z * rhs.y, lhs.w * rhs.y - lhs.x * rhs.z + lhs.y * rhs.w + lhs.z * rhs.x, lhs.w * rhs.z + lhs.x * rhs.y - lhs.y * rhs.x + lhs.z * rhs.w, }; } static vr::HmdVector3_t HmdVector3_From34Matrix( const vr::HmdMatrix34_t &matrix ) { return { matrix.m[ 0 ][ 3 ], matrix.m[ 1 ][ 3 ], matrix.m[ 2 ][ 3 ] }; } static vr::HmdVector3_t operator+( const vr::HmdMatrix34_t &matrix, const vr::HmdVector3_t &vec ) { vr::HmdVector3_t vector{}; vector.v[ 0 ] = matrix.m[ 0 ][ 3 ] + vec.v[ 0 ]; vector.v[ 1 ] = matrix.m[ 1 ][ 3 ] + vec.v[ 1 ]; vector.v[ 2 ] = matrix.m[ 2 ][ 3 ] + vec.v[ 2 ]; return vector; } static vr::HmdVector3_t operator*( const vr::HmdMatrix33_t &matrix, const vr::HmdVector3_t &vec ) { vr::HmdVector3_t result{}; result.v[ 0 ] = matrix.m[ 0 ][ 0 ] * vec.v[ 0 ] + matrix.m[ 0 ][ 1 ] * vec.v[ 1 ] + matrix.m[ 0 ][ 2 ] * vec.v[ 2 ]; result.v[ 1 ] = matrix.m[ 1 ][ 0 ] * vec.v[ 0 ] + matrix.m[ 1 ][ 1 ] * vec.v[ 1 ] + matrix.m[ 1 ][ 2 ] * vec.v[ 2 ]; result.v[ 2 ] = matrix.m[ 2 ][ 0 ] * vec.v[ 0 ] + matrix.m[ 2 ][ 1 ] * vec.v[ 1 ] + matrix.m[ 2 ][ 2 ] * vec.v[ 2 ]; return result; } static vr::HmdVector3_t operator-( const vr::HmdVector3_t &vec, const vr::HmdMatrix34_t &matrix ) { return { vec.v[ 0 ] - matrix.m[ 0 ][ 3 ], vec.v[ 1 ] - matrix.m[ 1 ][ 3 ], vec.v[ 2 ] - matrix.m[ 2 ][ 3 ] }; } static vr::HmdVector3d_t operator+( const vr::HmdVector3d_t &vec1, const vr::HmdVector3d_t &vec2 ) { return { vec1.v[ 0 ] + vec2.v[ 0 ], vec1.v[ 1 ] + vec2.v[ 1 ], vec1.v[ 2 ] + vec2.v[ 2 ] }; } static vr::HmdVector3_t operator+( const vr::HmdVector3_t &vec1, const vr::HmdVector3_t &vec2 ) { return { vec1.v[ 0 ] + vec2.v[ 0 ], vec1.v[ 1 ] + vec2.v[ 1 ], vec1.v[ 2 ] + vec2.v[ 2 ] }; } static vr::HmdVector3d_t operator-( const vr::HmdVector3d_t &vec1, const vr::HmdVector3d_t &vec2 ) { return { vec1.v[ 0 ] - vec2.v[ 0 ], vec1.v[ 1 ] - vec2.v[ 1 ], vec1.v[ 2 ] - vec2.v[ 2 ] }; } static vr::HmdVector3_t operator*( const vr::HmdVector3_t &vec, const vr::HmdQuaternion_t &q ) { const vr::HmdQuaternion_t qvec = { 0.0, vec.v[ 0 ], vec.v[ 1 ], vec.v[ 2 ] }; const vr::HmdQuaternion_t qResult = (q * qvec) * (-q); return { static_cast< float >( qResult.x ), static_cast< float >( qResult.y ), static_cast< float >( qResult.z ) }; } template < class T, class V > void HmdVector3_CovertVector( const T &in_vector, V &out_vector ) { out_vector.v[ 0 ] = in_vector.v[ 0 ]; out_vector.v[ 1 ] = in_vector.v[ 1 ]; out_vector.v[ 2 ] = in_vector.v[ 2 ]; }