我有一个包含编码旋转和位置数据的4x4变换矩阵的数组(我已经确认此矩阵表示Octave中的有效变换)。我想使用此数组的内容设置three.js对象(Object3D)的matrixWorld属性,即根据转换矩阵设置对象的位置和旋转。
根据来自three.js文档的this page和此处提出的各种问题(例如,this one和this one),似乎关键是要将nameOfObject.matrixAutoUpdate
设置为假。但是,考虑到这一点,我尝试了各种方法来设置nameOfObject.matrixWorld
,并且它们都没有改变渲染对象的位置:它保留在原点而没有旋转,就像这样当matrixWorld
是4x4单位矩阵时。
以下是我尝试过的内容(此代码在调用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);
一些注意事项:
matrixAutoUpdate
设置为false,但是现在我只是为了安全起见。nameOfObject.position
而不是更改matrixWorld
,则对象的位置会按预期更改,因此这并非如此似乎是一个渲染问题。updateMatrix()
,因为它会根据position
和rotation
属性覆盖矩阵。我假设updateMatrixWorld()
受到类似的考虑,但我还没有找到关于它做什么的讨论。任何建议将不胜感激!最糟糕的情况我会查看来源,但到目前为止,三个.js一直很容易使用,我怀疑我只是遗漏了一些东西。
答案 0 :(得分:2)
现在,我可以通过设置对象的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
似乎设置matrixWorld
不起作用。我认为当有问题的对象是scene
的孩子时这很好,但我可以想象如果对象是scene
的孩子的孩子并且有必要设置其世界位置,这会导致问题独立于其父级(编辑>,SceneUtils的attach
和detach
方法似乎允许这样做,尽管是间接的)。
我不会将此标记为答案,因为它实际上只是在对象的父级为scene
时才适用的解决方法。
暂且不说:我发现Matrix4.set()
使用行主要订单但Matrix4.fromArray()
和Matrix4.elements
使用列主要订单时有点奇怪。
答案 1 :(得分:0)
浏览源代码。
updateMatrix: function () {
this.matrix.compose( this.position, this.quaternion, this.scale );
this.matrixWorldNeedsUpdate = true;
},
我们看到Object3D的矩阵是根据其位置,四元数和比例参数构建的。
因此,与其设置矩阵,不如设置构成矩阵的各个部分可能更容易。
例如,此代码转换场景,使其居中于范围中间,并缩放以适合场景。
let xrange = xmax-xmin, yrange = ymax-ymin, zrange = zmax-zmin;
let range = (xrange+yrange+zrange)/3;
scene.scale.set(2/range,2/range,2/range);
scene.position.set( -(xmax+xmin)/2, -(ymax+ymin)/2, -(zmax+zmin)/2);
seene.updateMatrix();