【问题标题】:Three.js - VRControls integration - How to move in the scene?Three.js - VRControls 集成 - 如何在场景中移动?
【发布时间】:2015-08-11 06:06:20
【问题描述】:

我使用 Three.js 在一个小场景中渲染和移动(我的 orbitControl 更改 camera.position)。
现在我有眼裂。所以我添加了 VRControls 和 VREffect。
移动头部没有问题。
但我无法在场景中移动,因为 VRControls 会覆盖相机参数:

object.quaternion.copy( state.orientation ); // object is the camera

我认为这很容易纠正:我只需更新相机而不是覆盖它:

object.quaternion.copy(stateOrientationQuat.multiply(currentCameraQuat));

但它不起作用:它渲染了一个移动的轻弹场景。 VRControls 和 orbitControl 似乎在打架……

您能告诉我如何将 VRControls 集成到现有项目中吗?如果您有更新代码(我真的不知道四元数...),那会很有帮助。

谢谢

【问题讨论】:

    标签: three.js oculus virtual-reality webvr


    【解决方案1】:

    编辑:请参阅my other answer 以获得更好的方法。


    您可以通过创建一个作用于假相机的 VRControls 实例来组合这两个控件,然后在轨道控件上应用变换:

    相关sn-p:

    var orbitControls = new THREE.OrbitControls(camera);
    
    // Store the position of the VR HMD in a dummy camera.
    var fakeCamera = new THREE.Object3D();
    var vrControls = new THREE.VRControls(fakeCamera);
    
    ...
    
    var render = function() {
      requestAnimationFrame(render);
    
      orbitControls.update();
      vrControls.update();
    
      // Temporarily save the orbited camera position
      var orbitPos = camera.position.clone();
    
      // Apply the VR HMD camera position and rotation
      // on top of the orbited camera.
      var rotatedPosition = fakeCamera.position.applyQuaternion(
        camera.quaternion);
      camera.position.add(rotatedPosition);
      camera.quaternion.multiply(fakeCamera.quaternion);
    
      vrEffect.render(scene, camera);
    
      // Restore the orbit position, so that the OrbitControls can
      // pickup where it left off.
      camera.position.copy(orbitPos);
    };
    

    完整示例:

    var renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    var vrEffect = new THREE.VREffect(renderer, function () {});
    
    var camera = new THREE.PerspectiveCamera(
      75, window.innerWidth / window.innerHeight, 0.1, 1000);
    
    var orbitControls = new THREE.OrbitControls(camera);
    
    // Store the position of the VR HMD in a dummy camera.
    var fakeCamera = new THREE.Object3D();
    var vrControls = new THREE.VRControls(fakeCamera);
    
    var scene;
    var createScene = function () {
      scene = new THREE.Scene();
    
      scene.add(new THREE.PointLight());
    
      var cube = new THREE.Mesh(
        new THREE.BoxGeometry(1, 1, 1),
        new THREE.MeshLambertMaterial({
          color: 'green'
        })
      );
      cube.position.set(-1, -2, -5);
      scene.add(cube);
      orbitControls.target = cube.position;
    
      for (var i = 0; i < 10; i++) {
        cube = new THREE.Mesh(
          new THREE.BoxGeometry(1, 1, 1),
          new THREE.MeshLambertMaterial()
        );
        cube.position.set(
          (Math.random() - 0.5) * 20,
          (Math.random() - 0.5) * 20,
          (Math.random() - 0.5) * 20
        );
        scene.add(cube);
      }
    };
    createScene();
    
    var render = function() {
      requestAnimationFrame(render);
      
      orbitControls.update();
      vrControls.update();
      
      // Temporarily save the orbited camera position
      var orbitPos = camera.position.clone();
      
      // Apply the VR HMD camera position and rotation
      // on top of the orbited camera.
      var rotatedPosition = fakeCamera.position.applyQuaternion(
        camera.quaternion);
      camera.position.add(rotatedPosition);
      camera.quaternion.multiply(fakeCamera.quaternion);
      
      vrEffect.render(scene, camera);
      
      // Restore the orbit position, so that the OrbitControls can
      // pickup where it left off.
      camera.position.copy(orbitPos);
    };
    
    render();
    
    window.addEventListener('resize', function onWindowResize() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      vrEffect.setSize( window.innerWidth, window.innerHeight );
    }, false );
    <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/8125c7dac9bf0c7df19bd1d7d9695cbfc0425867/build/three.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/8125c7dac9bf0c7df19bd1d7d9695cbfc0425867/examples/js/effects/VREffect.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/8125c7dac9bf0c7df19bd1d7d9695cbfc0425867/examples/js/controls/VRControls.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/8125c7dac9bf0c7df19bd1d7d9695cbfc0425867/examples/js/controls/OrbitControls.js"></script>

    【讨论】:

    • 哇!我无法想象一个完整的答案!代码很简单,但我不会想到假相机。您的答案应该在 VRControls 文档中。非常感谢!
    • 对此现在“已弃用”的答案的评论:在一个项目中,我也必须暂时保存轨道摄像机四元数。我认为它不是必需的吗?
    【解决方案2】:

    我意识到有一种更简洁的方法可以做到这一点。您可以创建一个“小车”相机并将 VR 相机添加为子级。 然后,您可以让 OrbitControls 控制小车并让 VRControls 控制实际的相机,而无需进行繁琐的计算。

    相关sn-p:

    var camera = new THREE.PerspectiveCamera(
      75, window.innerWidth / window.innerHeight, 0.1, 1000);
    var vrControls = new THREE.VRControls(camera);
    
    var scene = new THREE.Scene();
    
    // The dolly has to be a PerspectiveCamera, as opposed
    // to a simple Object3D, since that's what
    // OrbitControls expects.
    var dollyCam = new THREE.PerspectiveCamera();
    var orbitControls = new THREE.OrbitControls(dollyCam);
    dollyCam.add(camera);
    scene.add(dollyCam);
    
    ...
    
    var render = function() {
      requestAnimationFrame(render);
    
      orbitControls.update();
      vrControls.update();
    
      vrEffect.render(scene, camera);
    };
    

    完整示例:

    var renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);
    
    var vrEffect = new THREE.VREffect(renderer);
    
    var camera = new THREE.PerspectiveCamera(
      75, window.innerWidth / window.innerHeight, 0.1, 1000);
    var vrControls = new THREE.VRControls(camera);
    var orbitControls;
    
    var scene;
    var createScene = function () {
      scene = new THREE.Scene();
    
      // The dolly has to be a PerspectiveCamera, as opposed
      // to a simple Object3D, since that's what
      // OrbitControls expects.
      var dollyCam = new THREE.PerspectiveCamera();
      orbitControls = new THREE.OrbitControls(dollyCam);
      dollyCam.add(camera);
      scene.add(dollyCam);
    
      scene.add(new THREE.PointLight());
    
      var cube = new THREE.Mesh(
        new THREE.BoxGeometry(1, 1, 1),
        new THREE.MeshLambertMaterial({
          color: 'green'
        })
      );
      cube.position.set(-1, -2, -5);
      scene.add(cube);
      orbitControls.target.copy(cube.position);
    
      for (var i = 0; i < 10; i++) {
        cube = new THREE.Mesh(
          new THREE.BoxGeometry(1, 1, 1),
          new THREE.MeshLambertMaterial()
        );
        cube.position.set(
          (Math.random() - 0.5) * 20,
          (Math.random() - 0.5) * 20,
          (Math.random() - 0.5) * 20
        );
        scene.add(cube);
      }
    };
    createScene();
    
    var render = function() {
      requestAnimationFrame(render);
      
      orbitControls.update();
      vrControls.update();
      
      vrEffect.render(scene, camera);
    };
    
    render();
    
    window.addEventListener('resize', function onWindowResize() {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      vrEffect.setSize( window.innerWidth, window.innerHeight );
    }, false );
    <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/r72/build/three.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/r72/examples/js/effects/VREffect.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/r72/examples/js/controls/VRControls.js"></script>
    <script src="https://cdn.rawgit.com/mrdoob/three.js/r72/examples/js/controls/OrbitControls.js"></script>

    【讨论】:

    • 我无法让 VRControls 在 Android 和 iOS 上使用上述代码。 OrbitControls(鼠标和触摸)似乎工作正常。这对你还有用吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 2019-04-09
    • 2015-08-02
    • 2013-01-28
    相关资源
    最近更新 更多