quat.fromToRotation with opposite vectors

I’ve posted this on the issue tracker, but I no longer have a bitbucket login so can’t keep up with it.

quat.fromToRotation(vec3(1,0,0), vec3(-1,0,0))

returns the identity rotation. Rather, it should return a rotation that achieves the goal of rotating vec3(1,0,0) to vec3(-1,0,0). Such a rotation is not unique, but they do exist so all that is needed is some way of choosing one out of the ones that work.

My code for this (in the pre-quat days when I used a vec4) was:

function (u,v)
        if v:cross(u):len() < tolerance then
            if v:dot(u) >= -tolerance then
                return vec4(1,0,0,0)
            end
            u = u:normalize()
            local a,b,c = abs(u.x), abs(u.y), abs(u.z)
            if a < b
            and a < c then
                v = vec3(0,-u.z,u.y)
            elseif b < c then
                v = vec3(u.z,0,-u.x)
            else
                v = vec3(u.y,-u.x,0)
            end
        else
            u = u:normalise()
            v = u + v:normalise()
        end
        v = v:normalise()
        local d = u:dot(v)
        u = u:cross(v)
        return vec4(d,u.x,u.y,u.z)
    end

(tolerance was to say that the two vectors don’t have to be exactly opposite for this to kick in so that I didn’t run in to very small numbers in the arithmetic.)

Thanks for reporting the issue @LoopSpace — this is our implementation of fromToRotation

        auto fromToRotation = [] (glm::vec3 u, glm::vec3 v)
        {
            u = glm::normalize(u);
            v = glm::normalize(v);
            glm::quat q;
            glm::vec3 a = glm::cross(u,v);
            q.x = a.x;
            q.y = a.y;
            q.z = a.z;
            float len = glm::length(u) * glm::length(u) * glm::length(v) * glm::length(v);
            q.w = std::sqrtf(len) + glm::dot(u, v);
            return glm::normalize(q);
        };

I can see it has problems, will try updating it with yours

I’ve put your version into the latest 3.2.9 beta

Fabulous!