2012-07-04 95 views
5

我試圖從一個文件加載到Three.js(自定義格式,不是Three.js支持的)一個場景。這種特殊格式描述了一個場景圖,其中樹中的每個節點都有一個指定爲4x4矩陣的變換。將其推入Three.js的過程如下所示:使用矩陣變換Three.js場景圖

// Yeah, this is javascript-like psuedocode 
function processNodes(srcNode, parentThreeObj) { 
    for(child in srcNode.children) { 
     var threeObj = new THREE.Object3D(); 

     // This line is the problem 
     threeObj.applyMatrix(threeMatrixFromSrcMatrix(child.matrix)); 

     for(mesh in child.meshes) { 
      var threeMesh = threeMeshFromSrcMesh(mesh); 
      threeObj.add(threeMesh); 
     } 

     parentThreeObj.add(threeObj); 

     processNodes(child, threeObj); // And recurse! 
    } 
} 

或者至少這就是我所希望的。正如我指出的那樣,applyMatrix行不符合我的預期。大部分場景看起來不錯,但某些已旋轉的元素沒有正確對齊(而其他元素則很奇怪)。

翻閱COLLADA加載程序(它的功能與我試圖做的大致相同),看起來它們是decompose the matrix的翻譯/旋轉/縮放並單獨應用。我想,在地方applyMatrix的上面顯示:

var props = threeMatrixFromSrcMatrix(child.matrix).decompose(); 
threeObj.useQuaternion = true; 
threeObj.position = props[ 0 ]; 
threeObj.quaternion = props[ 1 ]; 
threeObj.scale = props[ 2 ]; 

這再次產生一個場面,大部分元素都在正確的地方,但網格,以前都是錯位現已地方,不再轉化成遺忘根本不出現。所以最後這不比上面的applyMatrix好。

通過幾個關於該主題的在線討論,似乎推薦使用矩陣進行變換的方式是將它們直接應用於幾何體,而不是節點,因此我嘗試通過手動構建變換矩陣,如下所示:

function processNodes(srcNode, parentThreeObj, parentMatrix) { 
    for(child in srcNode.children) { 
     var threeObj = new THREE.Object3D(); 

     var childMatrix = threeMatrixFromSrcMatrix(child.matrix); 
     var objMatrix = THREE.Matrix4(); 
     objMatrix.multiply(parentMatrix, childMatrix); 

     for(mesh in child.meshes) { 
      var threeMesh = threeMeshFromSrcMesh(mesh); 
      threeMesh.geometry.applyMatrix(objMatrix); 
      threeObj.add(threeMesh); 
     } 

     parentThreeObj.add(threeObj); 

     processNodes(child, threeObj, objMatrix); // And recurse! 
    } 
} 

這實際上會產生正確的結果! (減去法線方面的一些怪癖,但我可以指出這一點)這很好,但問題是我們現在已經有效地展開了場景層次結構:更改父級變換會在子級上產生意想不到的結果,因爲滿變換堆棧現在被「烘烤」到網格中。在這種情況下,這是對現場信息的不可接受的損失。

那麼,如何告訴Three.js做相同的邏輯,但是在場景圖中的適當位置呢?

(對不起,我倒是十分想發佈一些活的代碼示例但是這不幸的是沒有這種情況的一個選項。)

回答

5

您可以使用matrixAutoUpdate = false以跳過three.js所場景圖位置/縮放/旋轉的東西。然後將object.matrix設置爲你想要的矩陣,所有的都應該是花花公子(好吧,它仍然會乘以父節點矩陣,所以如果你使用絕對模型視圖矩陣,你需要破解Object3D上的updateMatrixWorld方法。)

object.matrixAutoUpdate = false; 
object.matrix = myMatrix; 

現在,如果您想要在三層之上應用自定義轉換矩陣。js的位置/縮放/旋轉的東西,你需要編輯Object3D#updateMatrix是類似的。

THREE.Object3D.prototype._updateMatrix = THREE.Object3D.prototype.updateMatrix; 
THREE.Object3D.prototype.updateMatrix = function() { 
    this._updateMatrix(); 
    if (this.customMatrix != null) 
    this.matrix.multiply(this.customMatrix); 
}; 

https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L209

+0

相同的答案,間隔一分鐘。 :)但是,無論如何,謝謝! updateMatrix位非常有趣。 – Toji

5

唉...

的幾分鐘內Twitter上改變的感受性pointed out the solution我發佈這個。

這是一個簡單的單行修正:只需在Object3D實例上將matrixAutoUpdate設置爲false,並且第一個代碼示例按預期工作。

threeObj.matrixAutoUpdate = false; // This fixes it 
threeObj.applyMatrix(threeMatrixFromSrcMatrix(child.matrix)); 

它總是愚蠢的小事情,讓你...