I have an array containing a 4x4 transformation matrix encoding rotation and position data (I've already confirmed that this matrix represents a valid transformation in Octave). I'd like to set the matrixWorld property of a three.js object (an Object3D) using the contents of this array, i.e., set the position and rotation of the object based on the transformation matrix.
According to this page from the three.js documentation and various questions asked here (e.g., this one and this one), it seems the key is to set nameOfObject.matrixAutoUpdate
to false. However, with this accounted for, I've tried a variety of approaches to set nameOfObject.matrixWorld
and none of them change the location where the object is rendered: it remains at the origin with no rotation, as is the case when matrixWorld
is the 4x4 identity matrix.
Here's what I've tried (this code is inside an update method before render()
is called):
// 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);
A few notes:
matrixAutoUpdate
to false inside every iteration, but for now I've done so just to play it safe.nameOfObject.position
is modified based on the values in the fourth column of the transformation matrix instead of changing matrixWorld
, the object's position changes as expected, so this doesn't appear to be a rendering issue.updateMatrix()
shouldn't be called when manually setting the matrix as it overwrites it based on the position
and rotation
properties. I'd assume updateMatrixWorld()
is subject to similar considerations, but I haven't found as much discussion of what it does.Any suggestions would be appreciated! Worst case I'll look through the source, but three.js has been quite easy to use thus far and I suspect I'm simply missing something.
For now, I was able to achieve the desired result by setting the object's matrix
property (the local transform relative to the object's parent). Since the object's parent is scene
, code like this works:
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
It seems setting matrixWorld
just doesn't work. I suppose this is fine when the object in question is a child of scene
, but I can imagine this causing problems if the object is a child of a child of scene
and it's necessary to set its world position independent of its parent (edit: it appears that the attach
and detach
methods of SceneUtils would permit this, albeit indirectly).
I won't be marking this as the answer since it's really just a workaround that applies only when the object's parent is scene
.
An aside: I find it a little odd that Matrix4.set()
uses row-major order but Matrix4.fromArray()
and Matrix4.elements
use column-major order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With