void GLViewController::set_view_param(const Vec3f& e, const Vec3f& c, const Vec3f& u)
{
    // native viewing direction is the negative z-axis
    // while right is the x-axis and up is the y-axis
    Vec3f view = c - e;
    float eye_dist = length(view);
    view /= eye_dist;
    Vec3f right = normalize(cross(view, u));
    Vec3f up = cross(right, view);
    Mat3x3f rot(right, up, -view);
    rot = transpose(rot); // since matrix is row-major

    // convert the change-of-basis matrix to a quaternion
    Quatf qrot;
    qrot.make_rot(rot);
    set_rotation(qrot);
    set_centre(c);
    set_eye_dist(eye_dist);
}