Rui d'Orey
Rui d'Orey

Reputation: 1022

three.js - Quaternions for rotation matrix of a mesh in relation to the camera when that mesh has a parent?

From a tracking system I have access to a neck 4x4 transform matrix in relation to the camera (NeckWRTCameraMatrix).

I need to animate in three.js the neck bone that has as parent other bone but in a way that the rotation of the neck is in relation to the camera.

var m = new THREE.Matrix4();
m.fromArray(NeckWRTCameraMatrix);

var quaternion = new THREE.Quaternion();
quaternion.setFromRotationMatrix(m);

head.boneByName("Joint_Neck").quaternion.copy(quaternion);

However this rotates the bone in 180 degrees. How do I apply the rotation wrt camera as the rotations are in relation to the parent?

Thank you

EDIT: So probably what I need is get the rotation of the neck wrt camera in relation to the world.. some operation between the camera rotation transform and the matrix I got ?

Upvotes: 0

Views: 3021

Answers (1)

Rui d'Orey
Rui d'Orey

Reputation: 1022

After researching I got there this way, might help someone with quaternion problems:

  1. Extracted quaternion from the first frame rotation matrix and conjugated it to get the inverse direction rotation. This will work as the initial pose quaternion

    initial_quaternion = new THREE.Quaternion();
    initial_quaternion.setFromRotationMatrix(m);
    initial_quaternion.conjugate();
    
  2. For each frame extracted the quaternion and multiplied for the first quaternion, so I got the composed rotation of both quaternions (being the first inverted, that conjugation will give the difference from the initial rotation instead of the sum). As I wanted the rotation of neck bone in relation to head bone, this works great.

    var quaternion = new THREE.Quaternion();  
    quaternion.setFromRotationMatrix(m);
    quaternion.multiply(initial_quaternion);
    
  3. After having that, as the head and neck movement have a composed rotation of 50% of the total movement, I wanted to give a 50% weight to the rotation. To that, interpolated a neutral pose quaternion by the resulted quaternion in 2 with t = 0.5

    var basicQuaternion = new THREE.Quaternion();
    quaternion.slerp(basicQuaternion,0.5);
    
  4. Applied that quaternion to both neck and head bones (axis in the mesh are different from the ones as input) .

    head.boneByName("Joint_Head").quaternion.set(
          quaternion.y,
          quaternion.z,
          quaternion.x,
          quaternion.w
    );
    
    head.boneByName("Joint_Neck").quaternion.set(
          quaternion.y,
          quaternion.z,
          quaternion.x,
          quaternion.w
    );
    

Upvotes: 1

Related Questions