quat_slerp Function

public pure function quat_slerp(t, a, b) result(q)

Spherical linear interpolation from a (t = 0) to b (t = 1), along the shorter arc; linear when the two are nearly equal. As OpenSceneGraph's osg::Quat::slerp, which OpenFrames' TrajectoryFollower uses, except that the linear case is normalized (OSG's isn't: a quaternion a little short of unit length, its rotation matrix then also scaling, by a millionth for attitudes 0.25 deg apart, a kilometre at the Moon's distance).

Arguments

Type IntentOptional Attributes Name
real(kind=wp), intent(in) :: t

the fraction of the way (0 to 1)

real(kind=wp), intent(in) :: a(4)

unit quaternions [x, y, z, w] at t = 0 and t = 1

real(kind=wp), intent(in) :: b(4)

unit quaternions [x, y, z, w] at t = 0 and t = 1

Return Value real(kind=wp), (4)


Called by

proc~~quat_slerp~~CalledByGraph proc~quat_slerp quat_slerp proc~camera_between camera_between proc~camera_between->proc~quat_slerp proc~interpolate_attitude interpolate_attitude proc~interpolate_attitude->proc~quat_slerp proc~fly fly proc~fly->proc~camera_between proc~state_at TrajectoryFollower%state_at proc~state_at->proc~interpolate_attitude proc~followed_pose followed_pose proc~followed_pose->proc~state_at proc~world_matrix_at ReferenceFrame%world_matrix_at proc~followed_pose->proc~world_matrix_at proc~place_camera place_camera proc~place_camera->proc~fly proc~update~2 TrajectoryFollower%update proc~update~2->proc~state_at proc~frame WindowProxy%frame proc~frame->proc~place_camera proc~local_matrix_at ReferenceFrame%local_matrix_at proc~local_matrix_at->proc~followed_pose proc~update ReferenceFrame%update proc~update->proc~followed_pose proc~update->proc~update~2 proc~drawable_update DrawableTrajectory%drawable_update proc~drawable_update->proc~update proc~fm_update FrameManager%fm_update proc~fm_update->proc~update proc~resize WindowProxy%resize proc~resize->proc~frame proc~run WindowProxy%run proc~run->proc~frame proc~sphere_update Sphere%sphere_update proc~sphere_update->proc~update proc~terrain_update TerrainBody%terrain_update proc~terrain_update->proc~update proc~world_matrix_at->proc~local_matrix_at proc~world_matrix_at->proc~world_matrix_at proc~data_to_shown data_to_shown proc~data_to_shown->proc~world_matrix_at proc~to_shown to_shown proc~to_shown->proc~data_to_shown proc~art_point_between art_point_between proc~art_point_between->proc~to_shown proc~to_shown_at to_shown_at proc~to_shown_at->proc~to_shown proc~art_point art_point proc~art_point->proc~to_shown_at proc~art_points art_points proc~art_points->proc~to_shown_at proc~intermediates_by_time intermediates_by_time proc~intermediates_by_time->proc~art_point_between proc~marker_point marker_point proc~marker_point->proc~to_shown_at proc~marker_point->proc~art_point proc~update_ribbon_tail RibbonArtist%update_ribbon_tail proc~update_ribbon_tail->proc~art_point_between proc~update_ribbon_tail->proc~art_point proc~update_tail CurveArtist%update_tail proc~update_tail->proc~art_point_between proc~update_tail->proc~art_point proc~write_segments write_segments proc~write_segments->proc~to_shown_at proc~add_intermediates add_intermediates proc~add_intermediates->proc~intermediates_by_time proc~intermediates_by_data intermediates_by_data proc~add_intermediates->proc~intermediates_by_data proc~intermediates_by_distance intermediates_by_distance proc~add_intermediates->proc~intermediates_by_distance proc~curve_pick curve_pick proc~curve_pick->proc~art_point proc~intermediates_by_data->proc~art_point proc~intermediates_by_distance->proc~art_point proc~marker_update MarkerArtist%marker_update proc~marker_update->proc~marker_point proc~marker_update->proc~add_intermediates proc~update_bounds update_bounds proc~marker_update->proc~update_bounds proc~segment_update SegmentArtist%segment_update proc~segment_update->proc~write_segments proc~update_bounds->proc~art_points proc~write_curve CurveArtist%write_curve proc~write_curve->proc~art_points proc~write_ribbon RibbonArtist%write_ribbon proc~write_ribbon->proc~art_points proc~drawable_pick DrawableTrajectory%drawable_pick proc~drawable_pick->proc~curve_pick

Source Code

    pure function quat_slerp(t, a, b) result(q)
        real(wp), intent(in) :: t           !! the fraction of the way (0 to 1)
        real(wp), intent(in) :: a(4), b(4)  !! unit quaternions [x, y, z, w] at t = 0 and t = 1
        real(wp) :: q(4)
        real(wp), parameter :: epsilon = 0.00001_wp
        real(wp) :: cos_omega, omega, sin_omega, scale_a, scale_b, to(4)
        cos_omega = dot_product(a, b)
        to = b
        if (cos_omega < 0.0_wp) then
            cos_omega = -cos_omega
            to = -b
        end if
        if (1.0_wp - cos_omega > epsilon) then
            omega = acos(cos_omega)
            sin_omega = sin(omega)
            scale_a = sin((1.0_wp - t) * omega) / sin_omega
            scale_b = sin(t * omega) / sin_omega
        else                                ! (close: linear, then normalized below)
            scale_a = 1.0_wp - t
            scale_b = t
        end if
        q = scale_a * a + scale_b * to
        if (1.0_wp - cos_omega <= epsilon) q = q / norm2(q)   ! (a unit quaternion: a rotation, not also a scale)
    end function quat_slerp