Search code examples
node.jsmaththree.jsquaternionseuler-angles

How to get the original rotation Quaternion from the Euler in Three.js


I have an Euler calculated from a rotation Quaternion. I want to store the Euler and then load it somewhere else to calculate the original Quaternion. How can I achieve that?

const rot = new THREE.Quaternion(-0.00122, 0.98602, -0.15773, -0.05371);
const {x, y, z} = new THREE.Euler().setFromQuaternion(
        rot,
        'YXZ',
      );
 // How to make rot1 euqal to rot (as close as possible)?
 const rot1 = new THREE.Quaternion().setFromEuler(new THREE.Euler(x, y, z));
 console.log(rot); // Quaternion {_x: -0.00122, _y: 0.98602, _z: -0.15773, _w: -0.05371}
 console.log(rot1); // Quaternion {_x: 0.0012199961779640698, _y: -0.9860197701687391, _z: -0.15688998318156033, _w: 0.056116464812051764}
 console.log(rot1.inverse()); // Quaternion {_x: -0.0012199961779640698, _y: 0.9860197701687391, _z: 0.15688998318156033, _w: 0.056116464812051764}

Directions are wrong and w error seems a bit big. Here is the fiddlejs


Solution

  • There is two problems here with your script.

    1) The Euler rotation axis order 'YXZ' is missing when creatin a quaternion from an Euler angle:

    const rot1 = new THREE.Quaternion().setFromEuler(new THREE.Euler(x, y, z, 'YXZ'));
    

    2) Quaternion and Euler angle have different precision. Use a function to get a smaller precision when convertion the Euler angle to Quaternion:

     // Update decimal precision
     const decimalPrecision = 100000;
     function updatePrecision(input) {
        return Math.round(input*decimalPrecision) / decimalPrecision;
     }
    
     const rot1SmallerPrecition = {
        x: -updatePrecision(rot1.x),
        y: -updatePrecision(rot1.y),
        z: -updatePrecision(rot1.z),
     }
    

    Here a fiddle with corrections