ファイルからThree.js(Three.jsがサポートするものではなくカスタム形式)にシーンをロードしようとしています。この特定の形式は、ツリー内の各ノードに4x4行列として指定された変換があるシーングラフを記述します。それを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ローダー(私がやろうとしているのとほぼ同じことを実行します)を見ると、マトリックスを変換/回転/スケールに分解し、それぞれを個別に適用しているように見えます。上記の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に同じロジックを実行するように、ただしシーングラフの適切なポイントで実行するように指示するにはどうすればよいでしょうか。
(申し訳ありませんが、ライブコードの例をいくつか投稿したいと思いますが、残念ながら、この場合はオプションではありません。)