Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/tensorflow/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Webgl 使用矩阵变换Three.js场景图_Webgl_Three.js_Scenegraph - Fatal编程技术网

Webgl 使用矩阵变换Three.js场景图

Webgl 使用矩阵变换Three.js场景图,webgl,three.js,scenegraph,Webgl,Three.js,Scenegraph,我正在尝试将场景从文件加载到Three.js(自定义格式,而不是Three.js支持的格式)。此特定格式描述了一个场景图,其中树中的每个节点都有一个指定为4x4矩阵的变换。将其推入Three.js的过程如下所示: // Yeah, this is javascript-like psuedocode function processNodes(srcNode, parentThreeObj) { for(child in srcNode.children) { var t

我正在尝试将场景从文件加载到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在场景图中的适当位置执行相同的逻辑呢

(对不起,我非常想发布一些实时代码示例,但不幸的是,在这种情况下,这不是一个选项。)

叹气

在我发布这篇文章的几分钟内,我就在推特上修改了Qualia

这是一个简单的单行修复:只需在Object3D实例上将
matrixAutoUpdate
设置为false,第一个代码示例就可以按预期工作

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

总是愚蠢的小事让你…

你可以使用matrixAutoUpdate=false跳过三个.js场景的位置/缩放/旋转内容。然后将object.matrix设置为所需的矩阵,所有矩阵都应该是dandy(好的,它仍然会与父节点矩阵相乘,因此如果使用绝对模型视图矩阵,则需要在Object3D上使用UpdateMatrix方法。)

现在,如果您想在三个.js position/scale/rotation文件的基础上应用自定义变换矩阵,则需要将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);
};

请参见相同的答案,间隔一分钟。(不过还是要谢谢你!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);
};