setPreTransformMatrix does not affect triangle visibility

From the naming and documentation I would assume that setPreTransformMatrix is equivalent to VertexData.transform.

Playground: Babylon.js Playground

// ------------------------------------------

    function getVertexData() {
        return BABYLON.VertexData.CreateBox({ size: 1 });
        // let vertexData = new BABYLON.VertexData()
        // vertexData.positions = [
        //     0,0,0,
        //     0,0,1,
        //     1,0,0
        // ]
        // vertexData.indices = [
        // 0,1,2
        // ]
        // return vertexData;

    }
// ------------------------------------------

    // flip y and z: https://gamedev.stackexchange.com/a/7917
    let matrixFlixYZ = BABYLON.Matrix.FromArray([
            1.0, 0.0, 0.0, 0.0,
            0.0, 0.0, 1.0, 0.0,
            0.0, 1.0, 0.0, 0.0,
            0.0, 0.0, 0.0, 1.0,
    ]);

// ------------------------------------------

    let mesh1 = new BABYLON.Mesh("mesh 1", scene);
    let vd1 = getVertexData();
    vd1.transform(matrixFlixYZ);
    vd1.applyToMesh(mesh1);
    mesh1.position = new BABYLON.Vector3(-1, 2, 0);
// ------------------------------------------

    let mesh2 = new BABYLON.Mesh("mesh 2", scene);
    let vd2 = getVertexData();
    vd2.applyToMesh(mesh2);
    mesh2.setPreTransformMatrix(matrixFlixYZ);
    mesh2.position = new BABYLON.Vector3(1, 2, 0);

// -----------------------------------------

so I would assume that mesh1 and mesh2 are equivalent.

As you can see, with VertexData.transform, the triangles are wrongly oriented and I can see the inside faces.
With setPreTransformMatrix the visibility is not affected.

Expected:

Both boxes should be “wrong”

Actual:

setPreTransformMatrix does not affect the triangle visibility


Context: I am importing triangles from an external, right handed system.


Also, it is not clear for me how setPreTransformMatrix works with regard to child nodes.

If I have


TransformNode1     (setPreTransformMatrix, rotation, position)
|- TransformNode2  (setPreTransformMatrix, rotation, position)
   |- Mesh         (setPreTransformMatrix, rotation, position)

then I would assume the WorldMatrix is calculated from inner to outer, so

Mesh.setPreTransformMatrix -> Mesh.rotation -> Mesh.position ->  TransformNode2.setPreTransformMatrix -> TransformNode2.rotation -> TransformNode2.position -> TransformNode1.setPreTransformMatrix -> TransformNode1.rotation -> TransformNode1.position

Is that correct?

Hey and welcome back!

This is where everything happen: Babylon.js/transformNode.ts at master · BabylonJS/Babylon.js · GitHub

setPreTransformMatrix is actually setting the pivot matrix.

More specifically here is where the composition happens: Babylon.js/transformNode.ts at master · BabylonJS/Babylon.js · GitHub

so: pivot x scale x rotation x translation

if you want to completely overwrite the world matrix, you can call mesh.freezeWorldMatrix(mat)

Thanks!

So it seems I can’t affect the triangle orientation at all through the world matrix.

I tried setting scale to (1, 1, -1), and I would have expected it to also show the “wrong” faces, but it did not.
So the only option seems to be to continue using VertexData.transform.

// ------------------------------------------

    let mesh3 = new BABYLON.Mesh("mesh 3", scene);
    let vd3 = getVertexData();
    vd3.applyToMesh(mesh3);
    mesh3.position = new BABYLON.Vector3(3, 2, 0);
    mesh3.scaling = new BABYLON.Vector3(1, 1, -1);

// ------------------------------------------

    let mesh4 = new BABYLON.Mesh("mesh 4", scene);
    let vd4 = getVertexData();
    let m4 = matrixFlixYZ.clone().addTranslationFromFloats(5, 2, 0);
    vd4.applyToMesh(mesh4);
    mesh4.freezeWorldMatrix(m4);


// -----------------------------------------

I had wanted to move away from it because I need to do some transformations in the original coordinate space.

So what I planned was

let rot : BABYLON.Matrix = // ... rotation in original right handed system
let move : BABYLON.Matrix = // ... translation in original right handed system
let turnOverMatrix : BABYLON.Matrix = // ...

mesh.setPreTransformMatrix( rot.multiply(move).multiply(turnOverMatrix).multiply(matrixFlipYZ) )

instead I’ll just do

let rot : BABYLON.Matrix = // ... rotation in original right handed system
let move : BABYLON.Matrix = // ... translation in original right handed system
let turnOverMatrix : BABYLON.Matrix = // ...

vertexData.transform(matrixFlipYZ)

mesh.setPreTransformMatrix( matrixFlipYZ.invert().multiply(rot).multiply(move).multiply(turnOverMatrix).multiply(matrixFlipYZ) )

sounds good!

You can also force the scene to be in right handed mode with scene.useRightHandedSystem: Scene - Babylon.js Documentation

1 Like