| 3709 | bool ImPlot3DQuat::operator!=(const ImPlot3DQuat& rhs) const { return !(*this == rhs); } |
| 3710 | |
| 3711 | ImPlot3DQuat ImPlot3DQuat::Slerp(const ImPlot3DQuat& q1, const ImPlot3DQuat& q2, double t) { |
| 3712 | // Clamp t to [0, 1] |
| 3713 | t = ImClamp(t, 0.0, 1.0); |
| 3714 | |
| 3715 | // Compute the dot product (cosine of the angle between quaternions) |
| 3716 | double dot = q1.x * q2.x + q1.y * q2.y + q1.z * q2.z + q1.w * q2.w; |
| 3717 | |
| 3718 | // If the dot product is negative, negate one quaternion to take the shorter path |
| 3719 | ImPlot3DQuat q2_ = q2; |
| 3720 | if (dot < 0.0) { |
| 3721 | q2_ = ImPlot3DQuat(-q2.x, -q2.y, -q2.z, -q2.w); |
| 3722 | dot = -dot; |
| 3723 | } |
| 3724 | |
| 3725 | // If the quaternions are very close, use linear interpolation to avoid numerical instability |
| 3726 | if (dot > 0.9995) { |
| 3727 | return ImPlot3DQuat(q1.x + t * (q2_.x - q1.x), q1.y + t * (q2_.y - q1.y), q1.z + t * (q2_.z - q1.z), q1.w + t * (q2_.w - q1.w)).Normalized(); |
| 3728 | } |
| 3729 | |
| 3730 | // Compute the angle and the interpolation factors |
| 3731 | double theta_0 = acos(dot); // Angle between input quaternions |
| 3732 | double theta = theta_0 * t; // Interpolated angle |
| 3733 | double sin_theta = sin(theta); // Sine of interpolated angle |
| 3734 | double sin_theta_0 = sin(theta_0); // Sine of original angle |
| 3735 | |
| 3736 | double s1 = cos(theta) - dot * sin_theta / sin_theta_0; |
| 3737 | double s2 = sin_theta / sin_theta_0; |
| 3738 | |
| 3739 | // Interpolate and return the result |
| 3740 | return ImPlot3DQuat(s1 * q1.x + s2 * q2_.x, s1 * q1.y + s2 * q2_.y, s1 * q1.z + s2 * q2_.z, s1 * q1.w + s2 * q2_.w); |
| 3741 | } |
| 3742 | |
| 3743 | double ImPlot3DQuat::Dot(const ImPlot3DQuat& rhs) const { return x * rhs.x + y * rhs.y + z * rhs.z + w * rhs.w; } |
| 3744 |
nothing calls this directly
no test coverage detected