【问题标题】:Translate camera horizontally and vertically with the arrow keys in WebGL使用 WebGL 中的箭头键水平和垂直平移相机
【发布时间】:2016-02-24 11:32:04
【问题描述】:

我正在 WebGL javascript 中使用键盘在 X 和 Y 轴上实现相机的简单移动。 问题是相机在世界坐标中移动,而不是相机的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;
    }

【问题讨论】:

  • 您想根据相机旋转移动吗?例如,当按下向上键时,它应该朝着它所面对的方向移动?在这种情况下,您将使用三角函数自己计算 x 和 y 分量(除非 WebGL 有内置的东西,我对此一无所知)
  • 是的,这就是我想要的,我认为 THREE.js 必须有一些东西可以轻松处理它。谢谢。
  • 如果你使用three.js,试试这个OrbitControls example

标签: javascript three.js webgl


【解决方案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%;
}
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js"&gt;&lt;/script&gt;

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%;
}
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r74/three.min.js"&gt;&lt;/script&gt;

【讨论】:

  • 我意识到用键盘移动时相机的旋转中心不会改变。这由以下人员定义:controls = new THREE.OrbitControls(camera, renderer.domElement); function Center(pos) { controls.center.x = pos.x; controls.center.y = pos.y; controls.center.z = pos.z; }
猜你喜欢
  • 2016-02-14
  • 1970-01-01
  • 1970-01-01
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多