Javascript 设置three.js对象的matrixWorld属性

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,但没有一种方法改变对象的渲染位置:它保持在原点,没有

我有一个数组,其中包含一个4x4变换矩阵,用于编码旋转和位置数据(我已经确认该矩阵表示一个有效的倍频程变换)。我想使用此数组的内容设置three.js对象(an)的matrixWorld属性,即根据变换矩阵设置对象的位置和旋转

根据three.js文档和这里提出的各种问题(如和),关键似乎是将
nameOfObject.matrixAutoUpdate
设置为false。然而,考虑到这一点,我尝试了多种方法来设置对象的名称。matrixWorld,但没有一种方法改变对象的渲染位置:它保持在原点,没有旋转,就像matrixWorld是4x4单位矩阵时的情况一样

以下是我尝试过的(在调用
render()
之前,此代码在更新方法中):

请注意:

  • 我希望实际上没有必要在每次迭代中将
    matrixautodate
    设置为false,但现在我这样做只是为了安全起见
  • 如果基于变换矩阵第四列中的值修改了
    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();