Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

quat.fromToRotation with opposite vectors

edited November 2020 in Bugs Posts: 509

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.)

Tagged:

Comments

  • SimeonSimeon Admin Mod
    Posts: 5,613

    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

  • SimeonSimeon Admin Mod
    Posts: 5,613

    I've put your version into the latest 3.2.9 beta

  • Fabulous!

Sign In or Register to comment.