Search code examples
three.jspolyfillswebvr

three.js / web-vr-boilerplate / polyfill - HMD to controlled object:Axis re-mapping does not re-map also rotation order/rules


I'm using your webvr-boilerplate and trying to map it to a human face mesh.

The way I do is is:

1) attach the camera to an eye bone

main js script:

//add camera to eye
mesh.skeleton.bones[ 22 ].add(camera);

//resets camera rotation
camera.rotation.set(0,0,0);

//looks at mesh up direction to face front
camera.lookAt( mesh.up );

//moves camera to middle of eyes 
camera.position.set(10,10,0);

2) change the webvr-manager.js to update the neck bone ( passed as argument on initialization ) position and rotation and in index.php I swap the axis to match the HMD ones with the ones of the bone:

webvr-manager.js:

if ( state.orientation !== null ) {

     object.quaternion.copy( state.orientation );

 }

if ( state.position !== null ) {

     object.position.copy( state.position ).multiplyScalar( scope.scale );

 }

main js script:

 /* INSIDE UPDATE CYCLE */

// mesh.rotation.y+=0.1;
controls.update();

//resets bone position to default
mesh.skeleton.bones[ neckVRControlBone ].position.set(neckInitPosition.x,neckInitPosition.y,neckInitPosition.z) ;


//ROTATION SWAP
mesh.skeleton.bones[ neckVRControlBone ].rotation.x = pivot.rotation.y;

mesh.skeleton.bones[ neckVRControlBone ].rotation.y = - pivot.rotation.z;

mesh.skeleton.bones[ neckVRControlBone ].rotation.z = - tempRotation;

UPDATE 28/10/2015:

to simplify and after some extra debug realised is not a clamp problem..

The restated problem is:

To map the VR controls to an object that has a different axis configuration of the HMD/Cardboard and keep the correct rotation rules. Example of object axis: * x - up * y - depth * z - side

Swapping the rotations by just object .rotation.x = object .rotation.z results that, after updating the controls, rotating to the side makes an undesired rotation after 45º.

The rotation rules for each axis are different :

  • x rotates until PI and after that inverts signal and keeps changing in the same direction it was;
  • y rotates until PI/2 and after inverts the direction (when increasing, starts decreasing)
  • z is equal to x.

Changed webvr-polyfill.js and got it fixed for keyboard/mouse with this:

MouseKeyboardPositionSensorVRDevice.prototype.getState = function() {
   // this.euler.set(this.phi, this.theta, 0, 'YXZ');
   this.euler.set( this.theta , 0, - this.phi, 'YXZ');

But no way similar line to other controllers (HMD, cardboard, etc.). Maybe it would be nice the rotation order and mapping could be available to the user. Thanks

Example - try an set swappedAxis = true in the js console and rotate the neck.


Solution

  • The main problem you are running into is gimbal lock because you are using Euler rotations. Use Quaternions to avoid this problem.

    Additionally, the axes on your mesh appear to be flipped, so you have to account for that.

    Instead of setting components of the rotation, just set the quaternion:

    mesh.skeleton.bones[neckVRControlBone].quaternion.set(
        pivot.quaternion.y,
        -pivot.quaternion.z,
        -pivot.quaternion.x,
        pivot.quaternion.w
    );