在 three.js 中向 DeviceOrientationControls 添加偏移量

Add offset to DeviceOrientationControls in three.js

我正在尝试在 deviceControls.update(); 命令后向相机添加偏移量。我使用 DeviceOrientationControls 如此 first example.

偏移量将是拖动手势的结果,如 this example.

中所示

当我将2个四元数相乘时(我试过a x b和b x a),最后的结果不正确。

这是我的操作:

const m1 = new THREE.Matrix4();
m1.lookAt(new THREE.Vector3(), camera.target, THREE.Object3D.DefaultUp.clone());

const quater = new THREE.Quaternion();
quater.setFromRotationMatrix(m1);

const finalQuater = new THREE.Quaternion();
finalQuater.multiplyQuaternions(quater, camera.quaternion);

camera.quaternion.copy(finalQuater);

camera.target 是我的最终拖动目标 (Vector3),camera.quaternion 已由 deviceControls.update() 设置并且等于相机方向,根据设备陀螺仪。

感谢您的帮助

更新:我试过更换旋转顺序,同样的问题。我认为是由于设备方向更新后原点发生变化,但找不到解决方法。

DeviceOrientationControls 现在有一个 属性 alphaOffsetAngle 和一个方法

controls.updateAlphaOffsetAngle( angle ); // angle is in radians

这将围绕 three.js 'Y' 轴旋转场景。

three.js r.77

    var rotY = 0;
    var rotX = 0;    
    function setObjectQuaternion(quaternion, alpha, beta, gamma, orient) {
        var zee = new THREE.Vector3( 0, 0, 1 );
        var euler = new THREE.Euler();
        var q0 = new THREE.Quaternion();
        var q1 = new THREE.Quaternion( -Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis

        if (screenOrientation == 0) {
            var vectorFingerY = new THREE.Vector3( 1, 0, 0 ); 
            var fingerQY = new THREE.Quaternion();
            fingerQY.setFromAxisAngle ( vectorFingerY, -rotX );
        }else if (screenOrientation == 180) {
            var vectorFingerY = new THREE.Vector3( 1, 0, 0 ); 
            var fingerQY = new THREE.Quaternion();
            fingerQY.setFromAxisAngle ( vectorFingerY, rotX );
        }else if (screenOrientation == 90) {
            var vectorFingerY = new THREE.Vector3( 0, 1, 0 ); 
            var fingerQY = new THREE.Quaternion();
            fingerQY.setFromAxisAngle ( vectorFingerY, rotX );
        }else if (screenOrientation == -90) {
            var vectorFingerY = new THREE.Vector3( 0, 1, 0 ); 
            var fingerQY = new THREE.Quaternion();
            fingerQY.setFromAxisAngle ( vectorFingerY, -rotX );
        }
        q1.multiply( fingerQY );

        euler.set( beta, alpha, - gamma, 'YXZ' );                       // 'ZXY' for the device, but 'YXZ' for us
        quaternion.setFromEuler( euler );                               // orient the device
        quaternion.multiply( q1 );                                      // camera looks out the back of the device, not the top
        quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) );    // adjust for screen orientation
    };

    function update(camera) {
        if (window.orientation !== undefined && window.orientation !== null) screenOrientation = window.orientation; 

        var alpha  = deviceOrientation.alpha ? THREE.Math.degToRad( deviceOrientation.alpha ) : 0; // Z
        var beta   = deviceOrientation.beta  ? THREE.Math.degToRad( deviceOrientation.beta  ) : 0; // X'
        var gamma  = deviceOrientation.gamma ? THREE.Math.degToRad( deviceOrientation.gamma ) : 0; // Y''
        var orient = screenOrientation       ? THREE.Math.degToRad( screenOrientation       ) : 0; // O
        setObjectQuaternion( camera.quaternion, alpha, beta, gamma, orient );
    };

将此添加到您的初始化 container.appendChild(renderer.domElement);

            renderer.domElement.addEventListener( 'touchstart', function (e) {
                if (controls) {
                    e.preventDefault();
                    e.stopPropagation();
                    tempX = e.touches[ 0 ].pageX;
                    tempY = e.touches[ 0 ].pageY;
                }
            }, false );
            renderer.domElement.addEventListener( 'touchmove', function (e) {
                if (controls) {
                    e.preventDefault();
                    e.stopPropagation();
                    rotY += THREE.Math.degToRad((tempX - e.touches[ 0 ].pageX)/4);
                    rotX += THREE.Math.degToRad((tempY - e.touches[ 0 ].pageY)/4);

                    mesh.quaternion.copy(MeshStartQY);
                    var vectorFingerY = new THREE.Vector3( 0, 1, 0 ); 
                    var fingerQY = new THREE.Quaternion();
                    fingerQY.setFromAxisAngle ( vectorFingerY, rotY );

                    mesh.quaternion.multiply(fingerQY);

                    tempX = e.touches[ 0 ].pageX;
                    tempY = e.touches[ 0 ].pageY;
                }
            }, false );