c++quaternionsglm-math

Spherical interpolation between two points in GLM for OpenGL


I'm trying to interpolate between two points on a sphere to make a simple camera following an arc. Quaternions are utterly incomprehensible to me, so I've been trying to hack something together through trial and error.

Here's the gist of the code:

glm::vec3 camera_start_pos = {-0.282546, 1.525186, -2.946500};
glm::vec3 camera_end_pos = {-2.086190, 1.957833, 1.466586};

camera_pos_start_q = glm::rotation(camera_start_pos, vec3(1,1,1));
camera_pos_end_q = glm::rotation(camera_end_pos, vec3(1,1,1));

float cur_time = (sin(glfwGetTime())+1.f)/2.f;
auto pos_slerp = glm::slerp(camera_pos_start_q, camera_pos_end_q, cur_time);

camera_pos = pos_slerp * vec3(1,1,1);
view = glm::lookAt(camera_pos,
    camera_pos + camera_front,
    camera_up);

This code does produce some interpolated movement, but not between the positions I want to.

What vectors do I need to use in the calls to glm::rotation to get the right quaternions? What do i need to multiply pos_slerp by to interpolate between camera_start_pos and camera_end_pos?

Is there a way to interpolate between these two points in an arc-like manner without quaternions (or including some spline library)?


Solution

  • I don't now the library you use but here is the method.

    // x1: starting point of the arc
    // x2: ending point of the arc
    // cp: center of the arc
    // R: radius of the arc
    // t: interpolating value, between 0 and 1
    
    // compute vectors from center to starting/ending point
    // (these are coordinate-wise subtractions)
    sp = x1 - cp 
    ep = x2 - cp 
    // compute the lengths of these vectors
    lsp = sqrt(sum(sp^2))
    lep = sqrt(sum(ep^2))
    // scale the vectors
    s1 = lep * sp
    s2 = lsp * ep
    // compute the common length of s1 and s2
    l = sqrt(sum(s1^2))
    // normalize s1 and s2
    s1 = s1 / l
    s2 = s2 / l
    // compute angle between s1 and s2
    phi = acos(sum(s1 * s2)/(sqrt(sum(s1^2)) * sqrt(sum(s2^2))))
    // slerp
    slerp = cp + R * (sin((1-t)*phi)/sin(phi) * s1 + sin(t*phi)/sin(phi) * s2)
    

    I found this method in a R package and I have to say I don't understand everything: