title: Three.js First Person Controls
body: <p>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.</p>
  
  <p>Anyway, I took most of my code from the built-in FirstPersonControls, converted it to use pointer lock (<code>movementX</code> instead of <code>pageX - offset</code>), but I am having trouble smoothing the look motion.</p>
  
  <p>Here is my <code>onMouseMove</code> (using <code>originalEvent</code> since it is a jquery event):</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>And my <code>Controls.update()</code> (called on each animation frame, with the <code>THREE.Clock</code> delta):</p>
  
  <pre><code>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);
  }
  </code></pre>
  
  <p>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.</p>
  
  <p>You can see what I mean by "jumpy" <a href="http://static.pantherdev.com/dev/arena/client" rel="nofollow noreferrer">here</a>. I'm new to Three.js, WebGL, and just 3D in general so any help is appreciated.</p>
  
  <p>Thanks,</p>
  
  <p>-Chad</p>
  
  <hr>
  
  <p><strong>EDIT</strong> After working with <a href="https://stackoverflow.com/users/330242/przemo-li">@przemo_li</a>, here is the working code he came up with:</p>
  
  <pre><code>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);
  }
  </code></pre>