使用WebGL中的箭头键水平和垂直翻译相机

时间:2016-02-23 14:27:54

标签: javascript three.js webgl

我正在使用键盘在X和Y轴上实现WebGL javascript中相机的简单移动。 问题是相机在世界坐标中移动,而不是相机的X和Y,因此它不是真实的感觉,并且移动会根据相机的方向而改变。

这是一些代码(我不认为updateprojectionmatrix在这里是必要的:

var arrow = { left: 37, up: 38, right: 39, down: 40 };
    var delta = 100;
    switch (event.which) {
        case arrow.left:
            camera.position.x = camera.position.x - delta;
            camera.updateProjectionMatrix();
            break;
        case arrow.up:
            camera.position.y = camera.position.y + delta;
            camera.updateProjectionMatrix();
            break;
        case arrow.right:
            camera.position.x = camera.position.x + delta;
            camera.updateProjectionMatrix();
            break;
        case arrow.down:
            camera.position.y = camera.position.y - delta;
            camera.updateProjectionMatrix();
            break;
    }

1 个答案:

答案 0 :(得分:1)

See this article on cameras in WebGL

它显示了像这样的

计算相机的矩阵
+----+----+----+----+
| Xx | Xy | Xz |  0 |  <- x axis
+----+----+----+----+
| Yx | Yy | Yz |  0 |  <- y axis
+----+----+----+----+
| Zx | Zy | Zz |  0 |  <- z axis
+----+----+----+----+
| Tx | Ty | Tz |  1 |  <- camera position
+----+----+----+----+

因此,您应该能够通过将相机的世界x轴和/或y轴添加到其位置来沿着当前视图平面移动相机。

在three.js中,这将起作用

  var arrow = { left: 37, up: 38, right: 39, down: 40 };
  var delta = 0.05;
  var xAxis = new THREE.Vector3(
      camera.matrixWorld.elements[0], 
      camera.matrixWorld.elements[1], 
      camera.matrixWorld.elements[2]);
  var yAxis = new THREE.Vector3(
      camera.matrixWorld.elements[4], 
      camera.matrixWorld.elements[5], 
      camera.matrixWorld.elements[6]);

  switch (event.keyCode) {
    case arrow.left:
      camera.position.addScaledVector(xAxis, -delta);
      break;
    case arrow.up:
      camera.position.addScaledVector(yAxis, delta);
      break;
    case arrow.right:
      camera.position.addScaledVector(xAxis, delta);
      break;
    case arrow.down:
      camera.position.addScaledVector(yAxis, -delta);
      break;
  }

工作样本:

var renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

var directionalLight = new THREE.DirectionalLight(0xffffff, 1.125);
directionalLight.position.set( 1, 2, 0.5 );

directionalLight.position.normalize();
scene.add(directionalLight);

camera.position.x = 1;
camera.position.y = 0.75;
camera.position.z = 1.5;
camera.lookAt(new THREE.Vector3(0,0,0));

function render() {
  resize();  
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
render();

window.addEventListener('keydown', function(event) {
  event.preventDefault();
  var arrow = { left: 37, up: 38, right: 39, down: 40 };
  var delta = 0.05;
  var xAxis = new THREE.Vector3(
      camera.matrixWorld.elements[0], 
      camera.matrixWorld.elements[1], 
      camera.matrixWorld.elements[2]);
  var yAxis = new THREE.Vector3(
      camera.matrixWorld.elements[4], 
      camera.matrixWorld.elements[5], 
      camera.matrixWorld.elements[6]);
  
  switch (event.keyCode) {
    case arrow.left:
      camera.position.addScaledVector(xAxis, -delta);
      break;
    case arrow.up:
      camera.position.addScaledVector(yAxis, delta);
      break;
    case arrow.right:
      camera.position.addScaledVector(xAxis, delta);
      break;
    case arrow.down:
      camera.position.addScaledVector(yAxis, -delta);
      break;
  }
});
                        
function resize() {
  var canvas = renderer.domElement;
  var width = canvas.clientWidth;
  var height = canvas.clientHeight;
  if (canvas.width !== width || canvas.height !== height) {
    renderer.setSize(width, height, false);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
  }
}
html, body, canvas {
  margin: 0;
  width: 100%;
  height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js"></script>

Three.js还有一个translateOnAxis功能,所以你可以这样做

var arrow = { left: 37, up: 38, right: 39, down: 40 };
var delta = 0.05;
var xAxis = new THREE.Vector3(1,0,0);
var yAxis = new THREE.Vector3(0,1,0);

window.addEventListener('keydown', function(event) {
  event.preventDefault();
  switch (event.keyCode) {
    case arrow.left:
      camera.translateOnAxis(xAxis, -delta);
      break;
    case arrow.up:
      camera.translateOnAxis(yAxis, delta);
      break;
    case arrow.right:
      camera.translateOnAxis(xAxis, delta);
      break;
    case arrow.down:
      camera.translateOnAxis(yAxis, -delta);
      break;
  }
});       

工作样本:

var renderer = new THREE.WebGLRenderer();
document.body.appendChild(renderer.domElement);

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(75, 1, 0.1, 1000);

var geometry = new THREE.BoxGeometry(1, 1, 1);
var material = new THREE.MeshLambertMaterial({color: 0x00ff00});
var cube = new THREE.Mesh(geometry, material);
scene.add(cube);

var directionalLight = new THREE.DirectionalLight(0xffffff, 1.125);
directionalLight.position.set( 1, 2, 0.5 );

directionalLight.position.normalize();
scene.add(directionalLight);

camera.position.x = 1;
camera.position.y = 0.75;
camera.position.z = 1.5;
camera.lookAt(new THREE.Vector3(0,0,0));

function render() {
  resize();  
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}
render();

var arrow = { left: 37, up: 38, right: 39, down: 40 };
var delta = 0.05;
var xAxis = new THREE.Vector3(1,0,0);
var yAxis = new THREE.Vector3(0,1,0);

window.addEventListener('keydown', function(event) {
  event.preventDefault();
  switch (event.keyCode) {
    case arrow.left:
      camera.translateOnAxis(xAxis, -delta);
      break;
    case arrow.up:
      camera.translateOnAxis(yAxis, delta);
      break;
    case arrow.right:
      camera.translateOnAxis(xAxis, delta);
      break;
    case arrow.down:
      camera.translateOnAxis(yAxis, -delta);
      break;
  }
});
                        
function resize() {
  var canvas = renderer.domElement;
  var width = canvas.clientWidth;
  var height = canvas.clientHeight;
  if (canvas.width !== width || canvas.height !== height) {
    renderer.setSize(width, height, false);
    camera.aspect = width / height;
    camera.updateProjectionMatrix();
  }
}
html, body, canvas {
  margin: 0;
  width: 100%;
  height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js"></script>