Rei*_*ror 5 javascript 3d transform matrix three.js
我有一个包含编码旋转和位置数据的 4x4 变换矩阵的数组(我已经确认该矩阵表示 Octave 中的有效变换)。我想使用这个数组的内容设置一个 Three.js 对象(一个Object3D)的 matrixWorld 属性,即根据转换矩阵设置对象的位置和旋转。
根据three.js文档中的这个页面和这里提出的各种问题(例如,this one和this one),似乎关键是设置nameOfObject.matrixAutoUpdate为false。但是,考虑到这一点,我尝试了多种设置方法nameOfObject.matrixWorld,但没有一种方法会更改渲染对象的位置:它保持在原点,没有旋转,就像matrixWorld4x4 单位矩阵的情况一样。
这是我尝试过的(此代码在render()调用之前位于更新方法中):
// Setting up a three.js matrix
var tempMatrix = new THREE.Matrix4();
tempMatrix.fromArray(arrayContainingTransformationMatrix);
// Values are set as expected
console.log(tempMatrix.elements);
// Note that the approaches below were tried one at a time
// First approach (doesn't work)
nameOfObject.matrixAutoUpdate = false;
nameOfObject.matrixWorld.copy(tempMatrix);
// Second approach (also doesn't work)
// Based on the second SO question linked above
nameOfObject.matrixAutoUpdate = false;
nameOfObject.matrix.copy(tempMatrix);
nameOfObject.updateMatrixWorld(true);
// Third approach (this doesn't work either, unfortunately)
nameOfObject.matrixAutoUpdate = false;
nameOfObject.matrixWorld.fromArray(arrayContainingTransformationMatrix);
// Appears to be set correctly regardless of which approach is used
console.log(sphere1.matrixWorld.elements);
Run Code Online (Sandbox Code Playgroud)
一些注意事项:
matrixAutoUpdate在每次迭代中都设置为 false,但现在我这样做只是为了安全起见。nameOfObject.position根据变换矩阵的第四列中的值进行修改而不是更改matrixWorld,则对象的位置会按预期更改,因此这似乎不是渲染问题。updateMatrix()在手动设置矩阵时不应调用这些位置,因为它会根据position和rotation属性覆盖它。我假设updateMatrixWorld()受到类似的考虑,但我还没有找到太多关于它做什么的讨论。任何建议,将不胜感激!最坏的情况是我会查看源代码,但到目前为止 Three.js 一直很容易使用,我怀疑我只是遗漏了一些东西。
现在,我能够通过设置对象的matrix属性(相对于对象的父对象的局部变换)来实现所需的结果。由于该对象的父对象是scene,因此这样的代码可以工作:
scene.add(nameOfObject);
// Using this transformation matrix (translation of two units along the x axis):
// 1 0 0 2
// 0 1 0 0
// 0 0 1 0
// 0 0 0 1
// Column-major version of the transformation
var tempArrayCM = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 2, 0, 0, 1];
// Per the docs, Matrix4.fromArray() uses column-major format
// Row-major version of the transformation
var matrixT = new THREE.Matrix4();
matrixT.set(1, 0, 0, 2, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
// Per the docs, Matrix4.set() uses row-major format
nameOfObject.matrixAutoUpdate = false;
nameOfObject.matrix.fromArray(tempArrayCM); // This works
//nameOfObject.matrix.copy(matrixT); // This also works
//nameOfObject.matrixWorld.fromArray(tempArrayCM); // No effect
//nameOfObject.matrixWorld.copy(matrixT); // No effect
Run Code Online (Sandbox Code Playgroud)
似乎设置matrixWorld不起作用。我想当有问题的对象是 的子对象时这很好scene,但我可以想象如果该对象是 的子对象的子对象scene并且有必要独立于其父对象设置其世界位置(编辑:看来这会导致问题) SceneUtils的 和 方法将attach允许这样做,尽管是间接的)。detach
我不会将其标记为答案,因为它实际上只是一种仅当对象的父级为 时才适用的解决方法scene。
Matrix4.set()旁白:我发现使用行优先顺序但Matrix4.fromArray()使用Matrix4.elements列优先顺序有点奇怪。