Search code examples
javascriptmatrixthree.jstransformation

Completely replace the transformation matrix of a three.js object/mesh


Create object

A three.js mesh object is created:

    var geometry = new THREE.BufferGeometry();

    var standardMaterial = new THREE.MeshStandardMaterial( {/* inputs */ } );

    var mesh = new THREE.Mesh( geometry, standardMaterial );

    // Then mesh is added as an object to 3D scene.

Set transformation matrix

I intend to set the transformation matrix of the object:

            object = ... // Is already created and passed around.

            const pkm = ... // Containing 16 numbers, equivalent of a 4x4 matrix.

            var matrix = new THREE.Matrix4();

            matrix.set(
                pkm.X00, pkm.X01, pkm.X02, pkm.X03,
                pkm.X10, pkm.X11, pkm.X12, pkm.X13,
                pkm.X20, pkm.X21, pkm.X22, pkm.X23,
                pkm.X30, pkm.X31, pkm.X32, pkm.X33,
            );

            object.applyMatrix4( matrix );
            object.updateMatrixWorld( true );

Problem

The problem is that the above approach of setting transformation matrix just multiplies the new matrix into the previous matrix of the object. But we want the previous matrix to be completely replaced by the new matrix.

What is the best practice - most robust way - to replace the previous matrix of a three.js object/mesh with a completely new one?

AI chatbots

We tried some suggested solutions by AI tools offered by https://phind.com and https://poe.com. Some of them which failed are:

object.matrix = matrix;
object.matrixAutoUpdate = false;
object.updateMatrixWorld(true);
object.matrix.setFromMatrix4(matrix);
object.matrixWorldNeedsUpdate = true;
object.matrix.copy(matrix);
object.matrixWorldNeedsUpdate = true;
object.matrix.identity();
object.matrix.copy(newMatrix);  
object.updateMatrixWorld(true);
object.matrix.set(pkm.X00, pkm.X01, ... )
object.matrixAutoUpdate = false;
object.updateMatrixWorld(true);

Solution

  • Update

    The approach commented by @Mr.Coder should work fine:

    ... how it worked for me is, when you set a matrix manually, you actually have to turn matrixAutoUpdate to false and then do "not" use updateMatrix or updateMatrixWorld on it ... Taken from here: https://threejs.org/docs/#manual/en/introduction/Matrix-transformations

    Outdated answer

    Apparently, the position values of transformation matrix were the troublemaker. They have to be set manually after setting the matrix.

    Apparently, the latest working code is this:

    object = ... // Is already created and passed around.
    
    const pkm = ... // Containing 16 numbers, equivalent of a 4x4 matrix.
    
    var matrix = new THREE.Matrix4(); // Creating a new matrix.
    
    matrix.set(
        pkm.X00, pkm.X01, pkm.X02, pkm.X03,
        pkm.X10, pkm.X11, pkm.X12, pkm.X13,
        pkm.X20, pkm.X21, pkm.X22, pkm.X23,
        pkm.X30, pkm.X31, pkm.X32, pkm.X33,
    );
    
    object.applyMatrix4( matrix ); // Applying the new matrix to the object.
    object.updateMatrixWorld( true );
    
    
    // ** For some reason, the position has to be set separately.
    // ** Not sure why.
    object.position.copy( new Vector3( pkm.X03, pkm.X13, pkm.X23 ) );