Управление персоналом Three.js

Я играю с Three.js и WebGL и не могу получить элементы управления так, как я хочу. Я решил попробовать "свернуть свои" элементы управления, поскольку Three.js FirstPersonControls не использует блокировку указателя.

В любом случае, я взял большую часть своего кода из встроенного FirstPersonControls, преобразовал его в использование блокировки указателя (movementX вместо pageX - offset), но у меня проблемы с сглаживанием движения взгляда.

Вот мой 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;
}

И мой 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);
}

Этот код действительно работает, но перемещение камеры происходит, когда мышь перемещается. Я мог бы использовать некоторую помощь, чтобы выяснить, как сгладить ее.

Вы можете видеть, что я имею в виду под "прыгающим" здесь. Я новичок в Three.js, WebGL и просто 3D вообще, поэтому любая помощь приветствуется.

Спасибо,

-Chad


РЕДАКТИРОВАТЬ После работы с @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);
}

Ответ 2

1) Трудности? В вашем коде вы ограничиваете движение мыши X до - | + 85. Его маловероятно, чтобы такое ограничение было необходимо.

2) Совокупность всех событий, которые происходят во время кадра В вашем коде вы переопределяете движение мыши с каждым новым событием. Поэтому, если вы получите 3 события во время кадровой съемки, будут сохранены только самые последние.

Добавьте эти движения. Затем после кадра рендеринга вы можете очистить счетчик. И снова начните собирать события.