javascript Three.js 第一人称控制
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12500874/
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
Three.js First Person Controls
提问by Chad
I'm playing around with Three.js and WebGL and can't quite get the controls the way I want. I chose to try to "roll my own" controls since Three.js's FirstPersonControls do not use pointer lock.
我在玩 Three.js 和 WebGL,但不能完全按照我想要的方式获得控件。我选择尝试“滚动我自己的”控件,因为 Three.js 的 FirstPersonControls 不使用指针锁定。
Anyway, I took most of my code from the built-in FirstPersonControls, converted it to use pointer lock (movementX
instead of pageX - offset
), but I am having trouble smoothing the look motion.
无论如何,我从内置的 FirstPersonControls 中获取了大部分代码,将其转换为使用指针锁定(movementX
而不是pageX - offset
),但是我无法平滑外观运动。
Here is my onMouseMove
(using originalEvent
since it is a jquery event):
这是我的onMouseMove
(使用,originalEvent
因为它是一个 jquery 事件):
onMouseMove: function(e) {
if(!document.pointerLockElement) return;
var moveX = e.originalEvent.movementX ||
e.originalEvent.mozMovementX ||
e.originalEvent.webkitMovementX ||
0,
moveY = e.originalEvent.movementY ||
e.originalEvent.mozMovementY ||
e.originalEvent.webkitMovementY ||
0;
//Update the mouse movement for coming frames
this.mouseMovementX = moveX;
this.mouseMovementY = moveY;
}
And my Controls.update()
(called on each animation frame, with the THREE.Clock
delta):
而我的Controls.update()
(在每个动画帧上调用,带有THREE.Clock
增量):
update: function(delta) {
if(this.freeze) {
return;
}
//movement, works fine
if(this.moveForward) this.camera.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
if(this.moveBackward) this.camera.translateZ(actualMoveSpeed);
if(this.moveLeft) this.camera.translateX(-actualMoveSpeed);
if(this.moveRight) this.camera.translateX(actualMoveSpeed);
/////////
//ISSUES ARE WITH THIS CODE:
/////////
//look movement, really jumpy
this.lon += this.mouseMovementX;
this.lat -= this.mouseMovementY;
this.lat = Math.max(-85, Math.min(85, this.lat));
this.phi = (90 - this.lat) * Math.PI / 180;
this.theta = this.lon * Math.PI / 180;
this.target.x = this.camera.position.x + 100 * Math.sin(this.phi) * Math.cos(this.theta);
this.target.y = this.camera.position.y + 100 * Math.cos(this.phi);
this.target.z = this.camera.position.z + 100 * Math.sin(this.phi) * Math.sin(this.theta);
this.camera.lookAt(this.target);
}
This code does work, but moving the camera is jumpy as the mouse moves around. I could really use some help figuring out how to smooth it.
这段代码确实有效,但是随着鼠标的移动,移动相机会很跳跃。我真的可以使用一些帮助来弄清楚如何平滑它。
You can see what I mean by "jumpy" here. I'm new to Three.js, WebGL, and just 3D in general so any help is appreciated.
你可以在这里看到我所说的“跳跃”是什么意思。我是 Three.js、WebGL 和一般 3D 的新手,因此感谢任何帮助。
Thanks,
谢谢,
-Chad
-乍得
EDITAfter working with @przemo_li, here is the working code he came up with:
编辑与@przemo_li 合作后,这是他想出的工作代码:
onMouseMove: function(e) {
if(!document.pointerLockElement) return;
var moveX = e.originalEvent.movementX ||
e.originalEvent.mozMovementX ||
e.originalEvent.webkitMovementX ||
0,
moveY = e.originalEvent.movementY ||
e.originalEvent.mozMovementY ||
e.originalEvent.webkitMovementY ||
0;
//Update the initial coords on mouse move
this.mouseMovementX += moveX; //aggregate mouse movements as a total delta delta
this.mouseMovementY += moveY;
},
update: function(delta) {
if(this.freeze) {
return;
}
//movement
if(this.moveForward) this.camera.translateZ(-(actualMoveSpeed + this.autoSpeedFactor));
if(this.moveBackward) this.camera.translateZ(actualMoveSpeed);
if(this.moveLeft) this.camera.translateX(-actualMoveSpeed);
if(this.moveRight) this.camera.translateX(actualMoveSpeed);
//look movement
this.lon += this.mouseMovementX;
this.lat -= this.mouseMovementY;
this.mouseMovementX = 0; //reset mouse deltas to 0 each rendered frame
this.mouseMovementY = 0;
this.phi = (90 - this.lat) * Math.PI / 180;
this.theta = this.lon * Math.PI / 180;
if(this.constrainVertical) {
this.phi = THREE.Math.mapLinear(this.phi, 0, Math.PI, this.verticalMin, this.verticalMax);
}
this.target.x = this.camera.position.x + 100 * Math.sin(this.phi) * Math.cos(this.theta);
this.target.y = this.camera.position.y + 100 * Math.cos(this.phi);
this.target.z = this.camera.position.z + 100 * Math.sin(this.phi) * Math.sin(this.theta);
this.camera.lookAt(this.target);
}
回答by Air
'Official' version just added: https://github.com/mrdoob/three.js/blob/master/examples/js/controls/PointerLockControls.js
刚刚添加的“官方”版本:https: //github.com/mrdoob/three.js/blob/master/examples/js/controls/PointerLockControls.js
回答by przemo_li
1)Constraints? In your code you limit mouse X movement to -|+ 85 Its unlikely that such constraint is needed.
1)约束?在您的代码中,您将鼠标 X 移动限制为 -|+ 85 不太可能需要这种约束。
2)Aggregate all events that happen during frame In your code you override mouse movement with each new event. So if you get 3 events during frame only most recent will be stored.
2)聚合在帧期间发生的所有事件在您的代码中,您用每个新事件覆盖鼠标移动。因此,如果您在帧期间获得 3 个事件,则只会存储最近的事件。
Add those movements. Than after rendering frame you can clear count. And start gathering events again.
添加这些动作。比渲染帧后你可以清除计数。并再次开始收集事件。