2012-09-19 108 views
11

我在玩Three.js和WebGL,並且無法像我想要的那樣完全控制控件。因爲Three.js的FirstPersonControls不使用指針鎖,所以我選擇嘗試「滾動我自己的」控件。Three.js第一人稱控件

無論如何,我從內置的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); 
} 

這代碼確實可行,但隨着鼠標移動,移動攝像頭變得很麻煩。我真的可以用一些幫助來弄清楚如何平滑它。

你可以看到我的意思是「跳躍」here。我是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); 
} 
+0

你得到多少FPS? –

+0

@przemo_li這絕對不是FPS問題,我得到60FPS,就像我提到的機芯工作正常。如果我在它附近WASD是完全平滑的。我只需用鼠標做大手勢就會產生波濤洶涌的動作。我顯然只是沒有得到正確計算所需的數學。 – Chad

+0

mouseMovementX/Y在極端情況下的範圍是多少? –

回答

4

1)限制? 在您的代碼中,您將鼠標移動限制爲 - | + 85不太可能需要此類約束。

2)聚合框架內發生的所有事件 在您的代碼中,您將覆蓋每個新事件的鼠標移動。所以如果你在幀期間得到3個事件,最近將被存儲。

添加這些動作。除了渲染幀之後,您可以清除計數。並再次開始收集活動。

+0

完美地工作,謝謝! – Chad