javascript 三.js 在平面上旋转相机

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18834178/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 13:22:02  来源:igfitidea点击:

three.js rotate camera in plane

javascriptcamerarotationthree.jsperspectivecamera

提问by ostapische

I have a camera in my app:

我的应用程序中有一个摄像头:

camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
camera.position.z = 1;
camera.position.y = -5;
camera.rotateOnAxis(new THREE.Vector3(1, 0, 0), degInRad(90));
camera.up = new THREE.Vector3(0, 0, 1);  

Those code in renderfunction must rotate the camera while I'm pressing the keys:

render当我按下按键时,函数中的那些代码必须旋转相机:

if (leftPressed) {
    camera.rotateOnAxis((new THREE.Vector3(0, 1, 0)).normalize(), degInRad(1));
} else if (rightPressed) {
    camera.rotateOnAxis((new THREE.Vector3(0, 1, 0)).normalize(), degInRad(-1));
}
if (upPressed) {
    camera.rotateOnAxis((new THREE.Vector3(1, 0, 0)).normalize(), degInRad(1));
} else if (downPressed) {
    camera.rotateOnAxis((new THREE.Vector3(1, 0, 0)).normalize(), degInRad(-1));
}  

Camera rotates, but not in way I need. I want that camera rotates like in FPS (first person shooter) on plane. See picture to understand what I want...
I'm try to use sin(1)and cos(1)but can't understand how rotateOnAxisworks, cause translatefunctions work like a charm and moves camera in direction in what she sees.
P.S.
Here is a docsto the three.jsmaybe it helps.
To handle keyboard events I use KeyboardJS
And here is a degInRadfunction:

相机旋转,但不是我需要的方式。我希望相机像在飞机上的 FPS(第一人称射击游戏)一样旋转。查看图片以了解我想要什么......
我正在尝试使用sin(1)cos(1)但无法理解它是如何rotateOnAxis工作的,原因是translate功能像魅力一样工作,并将相机朝着她所看到的方向移动。
PS
这是一个文档three.js可能有帮助。
为了处理键盘事件,我使用KeyboardJS
这是一个degInRad函数:

function degInRad(deg) {
    return deg * Math.PI / 180;
}  

Link on JSFiddle

JSFiddle上的链接

camera rotation

相机旋转

O- position of camera
O-O1- current camera direction
R1- current rotation direction
R- direction what I want
Sorry for goodpicture.

O- 相机的位置
O-O1- 当前的相机方向
R1- 当前的旋转方向
R- 我想要的方向
对不起,拍得

回答by IceCreamYou

You might get what you want simply by setting camera.rotation.order = 'YXZ';

您可能只需通过设置即可获得您想要的 camera.rotation.order = 'YXZ';

回答by Darryl_Lehmann

believe what your looking for conceptually is a camera rig setup. In this approach you first build an Object3Dto be the "neck", then attach the camera to that object with your desired rotation. Then you can apply the rotations to the Object3Dto look around without the wobble effect. To carry it further you could nest that "neck" object in another Object3Dto act as the "body" and apply the translations to that object to move about the scene. In this way you have a basic camera controller rig. I modified your fiddle like so:

相信您在概念上寻找的是相机装备设置。在这种方法中,您首先构建一个Object3D作为“脖子”的对象,然后以您想要的旋转方式将相机连接到该对象上。然后,您可以将旋转Object3D应用于 环顾四周,而不会产生摆动效果。为了更进一步,您可以将该“颈部”对象嵌套在另一个对象中Object3D以充当“身体”,并将翻译应用于该对象以在场景中移动。这样你就有了一个基本的相机控制器装备。我像这样修改了你的小提琴:

Edit: implementation change to better suit @ostapische use case. Here's the fiddle link

编辑:实现更改以更好地适应@ostapische 用例。这是小提琴链接

function degInRad(deg) {
    return deg * Math.PI / 180;
}
/////////////////////////////////
function render() {
    requestAnimationFrame(render);
    if (leftPressed) {
        neck.rotation.y += degInRad(1);
    } else if (rightPressed) {
        neck.rotation.y -= degInRad(1);
    }
    if (upPressed) {
        camera.rotation.x += degInRad(1);
    } else if (downPressed) {
        camera.rotation.x -= degInRad(1);
    }
    renderer.render(scene, camera);
}
/////////////////////////////////
var scene, camera, renderer, grass, neck;
var leftPressed = false;
var rightPressed = false;
var upPressed = false;
var downPressed = false;
/////////////////////////////////
window.onload = function() {
    scene = new THREE.Scene();
    camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
    cameraHolder = new THREE.Object3D();
    cameraHolder.add( camera );
    renderer = new THREE.WebGLRenderer();
    renderer.rendererSize = {width: window.innerWidth, height: window.innerHeight, quality: 100, maxQuality: 400, minQuality: 20};
    renderer.setSize( renderer.rendererSize.width, renderer.rendererSize.height );
    document.body.appendChild( renderer.domElement );

    var texture, material, geometry, element;

    material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
    material.side = THREE.DoubleSide;
    geometry = new THREE.PlaneGeometry(24, 24);   
    grass = new THREE.Mesh( geometry, material );
    grass.name = "grass";
    scene.add( grass );

    neck = new THREE.Object3D();
    neck.rotateOnAxis(new THREE.Vector3(1, 0, 0), degInRad(90));
    neck.up = new THREE.Vector3(0, 0, 1);
    neck.position.z = 1;
    neck.position.y = -5;


    neck.add(camera);
    scene.add(neck);    

    KeyboardJS.on('left', function() { leftPressed = true; }, function() { leftPressed = false; });
    KeyboardJS.on('right', function() { rightPressed = true; }, function() { rightPressed = false; });
    KeyboardJS.on('up', function() { upPressed = true; }, function() { upPressed = false; });
    KeyboardJS.on('down', function() { downPressed = true; }, function() { downPressed = false; });

    render();
}

I was going to mention the PointLockControl or FirstPersonControl, but I see WestLangley has been so kind to suggest. Anyway good luck,

我本来打算提到 PointLockControl 或 FirstPersonControl,但我看到 WestLangley 提出的建议非常好。总之祝你好运