opengl-tutorials / ogl

http://www.opengl-tutorial.org
2.69k stars 925 forks source link

Angle calculation in RotationBetweenVectors #91

Closed johannesugb closed 5 years ago

johannesugb commented 5 years ago

I don't quite get it, why in RotationBetweenVectors, the cosine of the angle is calculated as s * 0.5f. The following is the relevant code, copied from the function:

    float s = sqrt( (1+cosTheta)*2 );
    float invs = 1 / s;

    return quat(
        s * 0.5f, 
        rotationAxis.x * invs,
        rotationAxis.y * invs,
        rotationAxis.z * invs
    );

Why is it not quat(cosTheta * 0.5f, rotationAxis * sin(acos(cosTheta)) * 0.5f)?

According to the explainations and the tool in [1], I would have thought that would be the way to go.

[1] Interactive quaternion exploration and learning tool by 3blue1brown and Ben Eater: https://eater.net/quaternions/video/intro

johannesugb commented 5 years ago

Okay, I was able to find out by myself.

I've read "The Shortest Arc Quaternion" in Game Programming Gems 1 by Stan Melax which this implementation is based on. There he states: "[...]the cross product [...] becomes small and potentially unstable when we try to normalize it[...]" and provides the solution which is numerically stable, resulting in the formulae used in the implementation of RotationBetweenVectors.

This, however, brings me to another question: The implementation provided by Stan Melax does not suggest to use case differentiations like if (cosTheta < -1 + 0.001f). So, are these really neccessary?

johannesugb commented 5 years ago

Okay, I've tried it. It really is a problem. Your code is great! Thank you. This issue is closed.