【问题标题】:three.js rotate camera in planethree.js 在平面上旋转相机
【发布时间】:2013-09-20 23:11:56
【问题描述】:

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

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);  

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));
}  

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

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

链接JSFiddle

O - 相机位置
O-O1 - 当前相机方向
R1 - 当前旋转方向
R - 我想要的方向
抱歉图片。

【问题讨论】:

  • 请考虑使用/修改THREE.PointerLockControls。见threejs.org/examples/misc_controls_pointerlock.html。请注意在指针锁定源代码中如何将相机添加为 2 个对象的子/孙子对象以实现您想要的效果。
  • @WestLangley,这是一个很好的链接,谢谢,但我不需要用鼠标移动相机。而camera 仅在controls = new THREE.PointerLockControls( camera ); scene.add( controls.getObject() ); 中使用——它是PointerLockControls 内部对象添加到场景中,而不是camera 本身和onWindowResize 函数中——只是应用新属性,在renderer.render( scene, camera ); 中——这里使用的是原始@987654349 @ 多变的。关于child/grandchild 你在说什么?实在看不懂,能解释一下吗?提前致谢。
  • 请注意PointerLockControls 如何随心所欲地旋转相机,但它使用鼠标而不是键盘。为了达到这个效果,它使用了pitchObjectyawObject 技术。请参阅源代码。这就是我所说的child/grandchild。您不必使用PointerLockControls;你可以自己实现类似的逻辑。
  • @WestLangley 这是我的失败。我在页面上没有看到PointerLockControls 的源代码。现在我试一试,如果一切顺利,我会回答一个问题或问你是否犯了错误。
  • @WestLangley 我写了工作示例there。但是我不明白为什么three.js 的开发人员在代码中使用那些pitchObject.rotation.x = Math.max( - PI_2, Math.min( PI_2, pitchObject.rotation.x ) ); 构造。当我在代码中取消注释此行时,垂直移动效果不好。你可以解释吗?谢谢。

标签: javascript camera rotation three.js perspectivecamera


【解决方案1】:

您只需设置camera.rotation.order = 'YXZ';就可以得到您想要的

【讨论】:

  • +1。是的,只需直接增加/减少camera.rotation.x.y
  • 我认为这是一个更好的解决方案,谢谢。现在我看到 Object3D.rotationEuler 而不是 Vector3 类型...
【解决方案2】:

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

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

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();
}

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

【讨论】:

  • 您的代码中有错误,但@WestLangley 给了我一个好主意,让我看看 PointerLockControls 的源代码。您能否将this 链接添加到您的答案或将您的代码修改为工作状态,我可以批准答案吗?
  • 好了,修改后的代码已经更新了。感谢您的考虑,感谢@WestLangley 的中肯建议。
猜你喜欢
  • 2013-07-29
  • 2021-08-23
  • 2013-07-15
  • 2016-01-20
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 2012-07-23
  • 2012-02-15
相关资源
最近更新 更多