Problem with matrix multiplication

According to math books, when multiplying matrices following is true:

(AB)C=A(BC)

Lets assume I have Matrices A, B and C. I multiply them together with babylonjs math:

const AB= A.multiply(B);
const ABC=AB.multiply( C );

Because the rule “(AB)C=A(BC)” should the following result same?

const BC= B.multiply( C );
const ABC=A.multiply(BC)

But I am not getting identical results, where is the problem?

It seems ok to me:

https://playground.babylonjs.com/#QPGDXH

Look at the console log.

2 Likes

You are right.
Because of floating numbers accuracy the results were not completely identical, and I was confused of scientific notation which makes very small numbers to look very different at first glance.

2 Likes

My problem was not fully solved so I had to dig deeper. It seems that after I invert matrices, they are no longer similar. Take a look: https://playground.babylonjs.com/#QPGDXH#1

When inverted, the matrices are totally different, for example the node 13 is on first matrix 13744307.000 but second 24520554.000

It’s because of a float precision problem.

Matrices store their components as 32 bits float and not 64 bits.

For testing purpose, I have performed some changes on my local copy to have matrices use 64 bits float instead (so Array instead of Float32Array), and it’s much better, even if not exactly equal:

2.8306351045,0.0000001191,0.0000001154,-0.0000000000,-0.0000005523,0.4227937602,
 0.0000005524,-0.0000000000,-43670253748.5334472656,42674406020.9739761353,
 43208142962.6059951782,-0.5000044421,43670305807.5326919556,-42674456892.8302230835, 
 -43208194469.7262496948,0.5000050381

2.8306352408,-0.0000000142,-0.0000000195,0.0000000000,0.0000000046,0.4227932161,
 0.0000000015,0.0000000000,-43670199647.2177734375,42674353153.3738937378,
 43208089433.7807312012,-0.5000038226,43670251706.1525268555,-42674404025.1671066284,
 -43208140940.8371810913,0.5000044187

I don’t see an easy solution here, as I don’t think updating the Matrix class to use 64 bits floats is planned… Maybe having an option to switch matrices to 64 bits could do it, but that would mean quite a lot of work to make all code depending on matrices work in both cases…

2 Likes

Thank you.
I wonder could matrix class be implemented in such way that you could pipe operations without the results being stored to actual underlying buffer until the last operation is finished. Then every calculation would happen with f64 while final results is saved f32

We are currently discussing with evgeni on a plan for you:) we need to make sure performance are kept unchanged

1 Like

If you solve this, its possible to make picking much faster.
Currectly, when picking, the babylonjs creates picking ray for each mesh by applying view matrix to model and then applying projection matrix to that.
If you can calculate multiplication of view and projection just once and then apply it to each mesh world matrix, one expensive matrix multiplication per mesh is saved.

Note that you can now switch matrix computation to 64 bits:

https://playground.babylonjs.com/#QPGDXH#3

You just have to set the useHighPrecisionMatrix parameter to true when creating the engine:

var createEngine = () => {
    return new BABYLON.Engine(canvas, false, {
        useHighPrecisionMatrix: true
    });
};
3 Likes

Thanks @Evgeni_Popov!