2

我使用 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 集成到现有项目中吗?如果您有更新代码(我真的不知道四元数...),那将非常有帮助。

谢谢

4

2 回答 2

6

编辑:请参阅我的其他答案以获得更好的方法。


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

相关片段:

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>

于 2015-05-28T17:41:43.560 回答
3

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

相关片段:

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>

于 2015-09-19T21:37:58.330 回答