Three.js First Person Controls

匿名 (未验证) 提交于 2019-12-03 01:49:02

问题:

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.

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.

Here is my onMouseMove (using originalEvent since it is a jquery event):

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

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.

Thanks,

-Chad


EDIT After working with @przemo_li, here is the working code he came up with:

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

回答1:

'Official' version just added: https://github.com/mrdoob/three.js/blob/master/examples/js/controls/PointerLockControls.js



回答2:

1)Constraints? In your code you limit mouse X movement to -|+ 85 Its unlikely that such constraint is needed.

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.

Add those movements. Than after rendering frame you can clear count. And start gathering events again.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!