Quaternion.setFromUnitVectors lacks precision for close to opposite vectors

Describe the bug

A Quaternion calculated using setFromUnitVectors doesn’t align the two unit vectors precisely if it get’s applied.

To Reproduce

run the following code using node (I’ve tested with 14.7.0) or check the live example on JSFiddle.

Code

const three = require("three");

const zAxis = new three.Vector3(0, 0, 1);
// just 3 example Vectors that fail
const normals = [
  new three.Vector3(0.00001630279256671349, 0.00021101192465278993, -0.9999999776040931).normalize(),
  new three.Vector3(-0.00011854270500476976, 0.00027142141201982574, -0.9999999561390212).normalize(),
  new three.Vector3(0.000042675541323141565, -0.00040869364504498944, -0.9999999155741478).normalize(),
];

normals.forEach(normal => {
  const alignNormalsRotation = new three.Quaternion().setFromUnitVectors(normal, zAxis);
  console.log(normal.clone().applyQuaternion(alignNormalsRotation).angleTo(zAxis));
});

Live example

Expected behavior
I would expect the calculations to have higher precision. I’ve only encounterd this amount of error with Vectors that are close to being opposite.

Result of the code:

0.00021164076687348634
0.000296178929600093
0.00041091569275236077

Expected result:

0
0
0

Platform:
Tested locally with:

  • Device: Desktop
  • OS: Windows 10
  • NodeJS: v14.7.0
  • Three.js version: three@0.110.0

and in the browser with:

3 thoughts on “Quaternion.setFromUnitVectors lacks precision for close to opposite vectors