我正在使用键盘在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;
}
答案 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>