Toj*_*oji 5 scenegraph webgl three.js
我正在尝试将文件中的场景加载到Three.js(自定义格式,而不是Three.js支持的格式).该特定格式描述了场景图,其中树中的每个节点具有指定为4×4矩阵的变换.将它推入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!
}
}
Run Code Online (Sandbox Code Playgroud)
或者至少那是我想要的.正如我所指出的那样,这applyMatrix条线路并不像我期望的那样工作.场景的大部分看起来都不错,但是已经旋转的某些元素没有正确对齐(而其他元素则很奇怪).
通过COLLADA加载器(我的工作大致相同),它们似乎将矩阵分解为平移/旋转/缩放并单独应用.我尝试用它代替上面显示的applyMatrix:
var props = threeMatrixFromSrcMatrix(child.matrix).decompose();
threeObj.useQuaternion = true;
threeObj.position = props[ 0 ];
threeObj.quaternion = props[ 1 ];
threeObj.scale = props[ 2 ];
Run Code Online (Sandbox Code Playgroud)
这再一次产生了一个场景,其中大多数元素都在正确的位置,但之前未对齐的网格现在已经转变为遗忘在某处并且根本不再出现.所以最后这并不比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!
}
}
Run Code Online (Sandbox Code Playgroud)
这实际上产生了正确的结果!(减去法线的一些怪癖,但我可以算出那个)这很好,但问题是我们现在已经有效地平整了场景层次结构:更改父级的转换会对孩子产生意想不到的结果,因为完整变换堆栈现在被"烘焙"到网格中.在这种情况下,这是关于场景的不可接受的信息丢失.
那么怎么可能会告诉Three.js做同样的逻辑,但是在场景图中的适当点呢?
(对不起,我非常希望发布一些实时代码示例,但遗憾的是,在这种情况下,这不是一个选项.)
叹...
在我发布这篇文章的几分钟内,Qualia 就在Twitter上指出了解决方案.
这是一个简单的单行修复:matrixAutoUpdate在Object3D实例上设置为false,第一个代码示例按预期工作.
threeObj.matrixAutoUpdate = false; // This fixes it
threeObj.applyMatrix(threeMatrixFromSrcMatrix(child.matrix));
Run Code Online (Sandbox Code Playgroud)
它总是让你感到愚蠢的小事......
您可以使用matrixAutoUpdate = false跳过Three.js场景图位置/比例/旋转内容.然后将object.matrix设置为你想要的矩阵,并且所有都应该是花花公子(好吧,它仍然会被父节点矩阵乘以,所以如果你使用绝对模型视图矩阵,你需要在Object3D上破解updateMatrixWorld方法.)
object.matrixAutoUpdate = false;
object.matrix = myMatrix;
Run Code Online (Sandbox Code Playgroud)
现在,如果你想在Three.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);
};
Run Code Online (Sandbox Code Playgroud)
请参阅https://github.com/mrdoob/three.js/blob/master/src/core/Object3D.js#L209
| 归档时间: |
|
| 查看次数: |
7762 次 |
| 最近记录: |