2012-07-04 25 views
5

Bir dosyadan bir sahne üç dosyaya yüklenmeye çalışıyorum (özel biçim, Three.js desteğini değil). Bu özel biçim, ağaçtaki her düğümün bir 4x4 matrisi olarak belirtilen bir dönüşüme sahip olduğu bir sahne grafiğini açıklar. Three.js'ye içine itmek için süreç şöyle görünür: Üç.js sahne grafiğini dönüştürmek için matrisler kullanma

// 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! 
    } 
} 

Ya da en azından ben olmak istiyorum ne

. İşaret ettiğim gibi, applyMatrix hattı beklediğim şekilde çalışmıyor. Sahnenin çoğunluğu iyi görünüyor, ancak döndürülmüş bazı öğeler düzgün şekilde hizalanmamış (diğerleri ise garip).

COLLADA yükleyiciyle (yaklaşık olarak aynı şeyi yapmaya çalıştığım) bakıldığında, decompose the matrix translate/rotate/scale şeklinde görünür ve her birini tek tek uygular.

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

Bu, bir kez daha, en elemanları doğru yerde bir sahne verir ama daha önce şimdi bir yerlerde ve artık unutulmaya dönüşmüş yanlış hizalanmış olduğunu kafes: Ben applyMatrix yerine yukarıda gösterilen çalıştı hiç görünmez. Yani sonunda bu, yukarıdan applyMatrix'dan daha iyi değil.

Konuyla ilgili birkaç çevrimiçi tartışmaya baktığınızda, dönüşümleriniz için matrisleri kullanmanın önerilen yolu, onları düğümlere değil, geometriye doğrudan uygulamaktır; bu nedenle, dönüşüm matrisini manuel olarak oluşturarak bunu denedim:

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! 
    } 
} 

Bu aslında doğru sonuçları verir! (eksi normlar ile biraz tuhaf ama bunu anlayabiliyorum) Bu harika, ama sorun şu ki, sahne hiyerarşisini etkili bir şekilde düzleştirdik: Bir ebeveyn üzerindeki dönüşümü değiştirmek, çocuklar üzerinde beklenmeyen sonuçlar doğuracaktır. Dönüşüm yığını artık kafeslere "pişiriliyor". Bu durumda bu sahne hakkında kabul edilemez bir bilgi kaybıdır.

Peki, Three.js'e aynı mantığı yapmak için, ancak sahne grafiğindeki uygun noktada nasıl söylenir?

(Üzgünüm, pahalıya bazı canlı kod örneklerini göndermek isterdim ama maalesef bu durumda bir seçenek yok.)

cevap

5

Sen Three.js skenograf konumu/ölçek/rotasyon şeyler atlamak için matrixAutoUpdate = false kullanabilirsiniz. Sonra object.matrix'i istediğiniz matrise ayarlayın ve tümünün dandy olması gerekir (iyi, hala ana düğüm matrisleriyle çarpılır, bu yüzden mutlak model görünümü matrislerini kullanıyorsanız, Object3D'de updateMatrixWorld yöntemini kesmeniz gerekir.)

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

Şimdi, Üçün üzerine uygulanan özel bir dönüştürme matrisine sahip olmak istiyorsanız.js pozisyon/ölçek/rotasyon şeyler, Object3D # updateMatrix gibi bir şey olması gerekir.

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

aynı cevabı arayla bir dakika bakın. :) Yine de teşekkürler! UpdateMatrix biti çok ilginç. – Toji

5

Sigh ... dakika içinde Twitter'da pointed out the solution Qualia Altered

Bunu gönderiyorum.

Tek satırlık basit bir düzeltme: Yalnızca, Object3D örneklerinde false değerini ayarlamak için matrixAutoUpdate'u ayarlayın ve ilk kod örneği amaçlandığı şekilde çalışır. Her zaman şunu elde aptal küçük şeyler

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

...

İlgili konular