mirror of
https://gitlab.freedesktop.org/monado/monado.git
synced 2024-12-29 11:06:18 +00:00
h/mercury: Add faster SwingTwistToQuaternion
This commit is contained in:
parent
e06dc0dda1
commit
9af195fea3
|
@ -220,25 +220,84 @@ SwingToQuaternion(const Vec2<T> swing, Quat<T> &result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// See
|
||||||
|
// https://gitlab.freedesktop.org/slitcch/rotation_visualizer/-/blob/da5021d21600388b07c9c81000e866c4a2d015cb/lm_rotations_story.inl
|
||||||
|
// for the derivation
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline void
|
inline void
|
||||||
SwingTwistToQuaternion(const Vec2<T> swing, const T twist, Quat<T> &result)
|
SwingTwistToQuaternion(const Vec2<T> swing, const T twist, Quat<T> &result)
|
||||||
{
|
{
|
||||||
//!@todo
|
|
||||||
// Rather than doing compound operations, we should derive it and collapse them.
|
|
||||||
Quat<T> swing_quat;
|
|
||||||
Quat<T> twist_quat;
|
|
||||||
|
|
||||||
Vec3<T> aax_twist;
|
T swing_x = swing.x;
|
||||||
|
T swing_y = swing.y;
|
||||||
|
|
||||||
aax_twist.x = (T)(0);
|
T theta_squared_swing = swing_x * swing_x + swing_y * swing_y;
|
||||||
aax_twist.y = (T)(0);
|
|
||||||
aax_twist.z = twist;
|
|
||||||
|
|
||||||
SwingToQuaternion(swing, swing_quat);
|
// So it turns out that we don't get any divisions by zero or nans in the
|
||||||
|
// differential part when twist is 0. I'm pretty sure we get lucky wrt. what cancels out
|
||||||
|
|
||||||
AngleAxisToQuaternion(aax_twist, twist_quat);
|
if (theta_squared_swing > T(0.0)) {
|
||||||
|
// theta_squared_swing is nonzero, so we the regular derived conversion.
|
||||||
|
|
||||||
QuaternionProduct(swing_quat, twist_quat, result);
|
T theta = sqrt(theta_squared_swing);
|
||||||
|
|
||||||
|
T half_theta = theta * T(0.5);
|
||||||
|
|
||||||
|
// the "other" theta
|
||||||
|
T half_twist = twist * T(0.5);
|
||||||
|
|
||||||
|
T cos_half_theta = cos(half_theta);
|
||||||
|
T cos_half_twist = cos(half_twist);
|
||||||
|
|
||||||
|
T sin_half_twist = sin(half_twist);
|
||||||
|
|
||||||
|
T sin_half_theta_over_theta = sin(half_theta) / theta;
|
||||||
|
|
||||||
|
result.w = cos_half_theta * cos_half_twist;
|
||||||
|
|
||||||
|
T x_part_1 = (swing_x * cos_half_twist * sin_half_theta_over_theta);
|
||||||
|
T x_part_2 = (swing_y * sin_half_twist * sin_half_theta_over_theta);
|
||||||
|
|
||||||
|
result.x = x_part_1 + x_part_2;
|
||||||
|
|
||||||
|
T y_part_1 = (swing_y * cos_half_twist * sin_half_theta_over_theta);
|
||||||
|
T y_part_2 = (swing_x * sin_half_twist * sin_half_theta_over_theta);
|
||||||
|
|
||||||
|
result.y = y_part_1 - y_part_2;
|
||||||
|
|
||||||
|
result.z = cos_half_theta * sin_half_twist;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// first: sin_half_theta/theta would be undefined, but
|
||||||
|
// the limit approaches 0.5.
|
||||||
|
|
||||||
|
// second: we only use theta to calculate sin_half_theta/theta
|
||||||
|
// and that function's derivative at theta=0 is 0, so this formulation is fine.
|
||||||
|
|
||||||
|
T half_twist = twist * T(0.5);
|
||||||
|
|
||||||
|
T cos_half_twist = cos(half_twist);
|
||||||
|
|
||||||
|
T sin_half_twist = sin(half_twist);
|
||||||
|
|
||||||
|
T sin_half_theta_over_theta = T(0.5);
|
||||||
|
|
||||||
|
// cos(0) is 1 so no cos_half_theta necessary
|
||||||
|
result.w = cos_half_twist;
|
||||||
|
|
||||||
|
T x_part_1 = (swing_x * cos_half_twist * sin_half_theta_over_theta);
|
||||||
|
T x_part_2 = (swing_y * sin_half_twist * sin_half_theta_over_theta);
|
||||||
|
|
||||||
|
result.x = x_part_1 + x_part_2;
|
||||||
|
|
||||||
|
T y_part_1 = (swing_y * cos_half_twist * sin_half_theta_over_theta);
|
||||||
|
T y_part_2 = (swing_x * sin_half_twist * sin_half_theta_over_theta);
|
||||||
|
|
||||||
|
result.y = y_part_1 - y_part_2;
|
||||||
|
|
||||||
|
result.z = sin_half_twist;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace xrt::tracking::hand::mercury::lm
|
} // namespace xrt::tracking::hand::mercury::lm
|
||||||
|
|
Loading…
Reference in a new issue