2012-09-19 29 views
11

Estoy jugando con Three.js y WebGL y no puedo obtener los controles del modo que quiero. Elegí intentar "hacer rodar mis propios controles" ya que los FirstPersonControls de Three.js no usan el bloqueo del puntero.Three.js First Person Controls

De todos modos, tomé la mayor parte de mi código del FirstPersonControls incorporado, lo convertí para utilizar el bloqueo del puntero (movementX en lugar de pageX - offset), pero estoy teniendo problemas para suavizar el movimiento de la apariencia.

Aquí es mi onMouseMove (usando originalEvent ya que es un evento 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; 
} 

Y mi Controls.update() (llamado en cada fotograma de la animación, con el 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); 
} 

Este El código funciona, pero al mover la cámara, el mouse se mueve. Realmente podría usar algo de ayuda para averiguar cómo suavizarlo.

Puedes ver lo que quiero decir con "jumpy" here. Soy nuevo en Three.js, WebGL, y solo 3D en general, así que cualquier ayuda es apreciada.

Gracias,

-Chad


EDIT Después de trabajar con @przemo_li, aquí está el código de trabajo que se le ocurrió:

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

¿Cuánto FPS qué se obtiene? –

+0

@przemo_li Definitivamente no es un problema de FPS, estoy recibiendo 60FPS y como mencioné el movimiento funciona bien. Si WASD alrededor es perfectamente suave. Solo tengo que hacer grandes gestos con el mouse para producir un movimiento entrecortado. Obviamente no obtengo los cálculos necesarios para hacer el cálculo correctamente. – Chad

+0

¿Qué rango llevará mouseMovementX/Y en extremos? –

Respuesta

4

1) Limitaciones? En su código, limita el movimiento del mouse X a - | + 85 Es poco probable que tal restricción sea necesaria.

2) Agregue todos los eventos que ocurran durante el cuadro En su código anula el movimiento del mouse con cada nuevo evento. Entonces, si obtienes 3 eventos durante el cuadro, solo se guardarán los más recientes.

Agregue esos movimientos. Luego de renderizar el fotograma, puedes borrar el conteo. Y comienza a reunir eventos de nuevo.

+0

Funciona perfectamente, gracias! – Chad