Sto tentando di caricare una scena da un file in Three.js (formato personalizzato, non uno supportato da Three.js). Questo particolare formato descrive un grafico di scena in cui ogni nodo dell'albero presenta una trasformazione specificata come matrice 4x4. Il processo per spingere in Three.js simile a questa:Utilizzo delle matrici per trasformare il grafico di scena 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!
}
}
O almeno questo è quello che mi piacerebbe che fosse. Come ho sottolineato, la linea applyMatrix
non funziona come mi aspetterei. La maggior parte della scena sembra a posto, ma alcuni elementi che sono stati ruotati non sono allineati correttamente (mentre altri sono, è strano).
Guardando attraverso il caricatore COLLADA (che fa approssimativamente la stessa cosa che sto tentando di fare) sembra che siano decompose the matrix in una traslazione/rotazione/scala e si applicano singolarmente. Ho provato che al posto del applyMatrix mostrato sopra:
var props = threeMatrixFromSrcMatrix(child.matrix).decompose();
threeObj.useQuaternion = true;
threeObj.position = props[ 0 ];
threeObj.quaternion = props[ 1 ];
threeObj.scale = props[ 2 ];
Questo, ancora una volta, produce una scena in cui la maggior parte elementi sono nel posto giusto ma ingrana che in precedenza erano disallinea ora sono state trasformate in oblio qualche parte e non più sembra affatto. Quindi alla fine non è meglio dello applyMatrix
dall'alto.
Guardando attraverso diverse discussioni online sull'argomento, sembra che il modo consigliato di utilizzare le matrici per le proprie trasformazioni consiste nell'applicarle direttamente alla geometria, non ai nodi, quindi l'ho provato costruendo manualmente la matrice di trasformazione in questo modo:
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!
}
}
Questo produce effettivamente i risultati corretti! (meno alcune stranezze con le normali, ma posso capirlo). È grandioso, ma il problema è che ora abbiamo effettivamente appiattito la gerarchia delle scene: cambiare la trasformazione su un genitore produrrà risultati inaspettati sui bambini perché il pieno trasformare lo stack è ora "cotto" nelle mesh. In questo caso è una perdita inaccettabile di informazioni sulla scena.
Quindi, come si può dire a Three.js di fare la stessa logica, ma al punto appropriato nel grafico della scena?
(Scusate, mi amerebbero di inviare alcuni esempi di codice in tensione ma che non è, purtroppo, un'opzione in questo caso.)
Stessa risposta, un minuto di distanza. :) Grazie comunque, però! Il bit updateMatrix è molto interessante. – Toji