Javascript 设置three.js对象的matrixWorld属性
我有一个数组,其中包含一个4x4变换矩阵,用于编码旋转和位置数据(我已经确认该矩阵表示一个有效的倍频程变换)。我想使用此数组的内容设置three.js对象(an)的matrixWorld属性,即根据变换矩阵设置对象的位置和旋转 根据three.js文档和这里提出的各种问题(如和),关键似乎是将Javascript 设置three.js对象的matrixWorld属性,javascript,matrix,3d,three.js,transform,Javascript,Matrix,3d,Three.js,Transform,我有一个数组,其中包含一个4x4变换矩阵,用于编码旋转和位置数据(我已经确认该矩阵表示一个有效的倍频程变换)。我想使用此数组的内容设置three.js对象(an)的matrixWorld属性,即根据变换矩阵设置对象的位置和旋转 根据three.js文档和这里提出的各种问题(如和),关键似乎是将nameOfObject.matrixAutoUpdate设置为false。然而,考虑到这一点,我尝试了多种方法来设置对象的名称。matrixWorld,但没有一种方法改变对象的渲染位置:它保持在原点,没有
nameOfObject.matrixAutoUpdate
设置为false。然而,考虑到这一点,我尝试了多种方法来设置对象的名称。matrixWorld,但没有一种方法改变对象的渲染位置:它保持在原点,没有旋转,就像matrixWorld是4x4单位矩阵时的情况一样
以下是我尝试过的(在调用render()
之前,此代码在更新方法中):
请注意:
- 我希望实际上没有必要在每次迭代中将
设置为false,但现在我这样做只是为了安全起见matrixautodate
- 如果基于变换矩阵第四列中的值修改了
,而不是更改nameOfObject.position
,则对象的位置会按预期更改,因此这似乎不是渲染问题matrixWorld
- 我在多个位置读到,手动设置矩阵时不应调用
,因为它会根据updateMatrix()
和位置
属性覆盖矩阵。我假设旋转
也会受到类似的考虑,但我还没有发现关于它的功能的太多讨论updateMatrix()
如有任何建议,将不胜感激!最糟糕的情况是,我会查看源代码,但是到目前为止,three.js非常容易使用,我怀疑我只是缺少了一些东西。现在,我可以通过设置对象的
矩阵
属性(相对于对象父对象的局部变换)来实现所需的结果。由于对象的父对象是场景
,因此类似这样的代码可以工作:
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就是不起作用。我认为,当所讨论的对象是场景
的子对象时,这很好,但我可以想象,如果该对象是场景
的子对象,并且有必要独立于其父对象设置其世界位置,则会导致问题(edit:的attach
和detach
方法似乎允许这样做,尽管是间接的)
我不会将此标记为答案,因为它实际上只是一种解决方法,仅当对象的父对象是场景时才适用
旁白:我觉得有点奇怪,Matrix4.set()
使用行大顺序,但Matrix4.fromArray()
和Matrix4.elements
使用列大顺序。查看源代码
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();
循环中必须有.updateMatrix(),对吗?没有,但它的省略与updateMatrix()
一致(即,在手动设置矩阵时不应调用它,因为它将使用位置和旋转属性计算的变换覆盖变换)。Matrix4.set()
使用行主顺序,因此当以块形式打印成4行时,代码是可读的。Matrix4.elements
使用列主顺序与webGL兼容。Matrix4.fromArray()
使用列主顺序与Matrix4.elements
兼容。直接设置matrixWorld没有意义,因为场景扩展了Object3D,即场景有自己的矩阵,场景中的所有对象也是Object3D的子对象,Object3D的变换应该影响其子对象。您只能设置对象的矩阵。您可以无法设置对象的世界矩阵。这是您的问题吗?“我如何设置object.matrix
,以便生成特定的对象。matrixWorld
——考虑对象父对象的变换?”如果对象的世界矩阵是只读的,这就回答了我的问题。我假设可以设置它,因为matrixWorld
属性在中没有标记为“readonly”(其他只读属性的描述,例如id
,以“readonly”开头)。它不是只读的。渲染器正在重置它。是否可以阻止渲染器执行此操作?(我意识到这不是必需的,因为SceneUtils
中有attach
和detach
方法)matrixAutoUpdate
的描述似乎意味着将其设置为false应该可以防止matrixWorld
和matrixWorld
的更新,但这似乎只会阻止matrixAutoUpdate
的更新。我试图理解您试图实现的目标。如果您在我的第一次演讲中回答这个问题t、 那会有帮助的。
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();