majidarif majidarif - 28 days ago 8
Python Question

Multiplying 4x3 affine transform matrices in javascript

I am trying to calculate transforms in Three.JS and honestly I'm new to 3D math.

In Three.JS there is a 3x3 and 4x4 matrix class but no 4x3.

Goal: I want to understand how to do multiplication on a 4x3*4x3 matrix.

I have a set of the inputs and the correct outputs. I got it by using python, because there is a library called

Noesis
that has multiplication of 4x3 matrices.

The problem is that the library calls from a python binary, so I can't see the source code.

The code in python is simply:
modelSpaceMat = boneMat * frameMat


Here is a sample of the correct dataset:

boneMat= (
(0.0, 0.0, 1.0),
(0.0, 1.0, 0.0),
(-1.0, 0.0, 0.0),
(0.0, 32.29199981689453, -3.2665998935699463)
)
frameMat= (
(0.6425124406814575, -0.06018795818090439, 0.7639083862304688),
(-0.003379624802619219, 0.9966778755187988, 0.08136376738548279),
(-0.7662678360939026, -0.05486864596605301, 0.640174925327301),
(4.438972473144531, -1.4769394397735596, 3.863013744354248)
)
modelSpaceMat=(
(-0.7639083862304688, -0.06018795818090439, 0.6425124406814575),
(-0.08136376738548279, 0.9966778755187988, -0.003379624802619219),
(-0.640174925327301, -0.05486864596605301, -0.7662678360939026),
(-1.1457012760729413e-07, 30.441999435424805, 9.592490357590577e-08)
)

boneMat= (
(1.0, 0.0, 0.0),
(0.0, 1.0, 0.0),
(0.0, 0.0, 1.0),
(0.0, 0.007000000216066837, -3.2665998935699463)
)
frameMat= (
(1.0000004768371582, 2.3320662876358256e-06, -1.4419805665966123e-05),
(2.817355607476202e-06, 0.9999991059303284, -3.3202520626218757e-06),
(1.5038006495160516e-05, -2.133270072590676e-06, 1.0000003576278687),
(-0.0015083501348271966, 0.02300064079463482, 3.266691207885742)
)
modelSpaceMat= (
(1.0000004768371582, 2.3320662876358256e-06, -1.4419805665966123e-05),
(2.817355607476202e-06, 0.9999991059303284, -3.3202520626218757e-06),
(1.5038006495160516e-05, -2.133270072590676e-06, 1.0000003576278687),
(-0.0014612301019951701, 0.030011480674147606, 9.013115777634084e-05)
)


Now I want to be able to do it with javascript.

Questions:


  • Is there any library available?

  • What is the formula?






The python module, Noesis, has this line:

def __mul__(self, other):
if isinstance(other, (NoeMat43, list, tuple)):
return noesis.mat43Mul(self, other)
elif isinstance(other, NoeVec3):
return noesis.mat43TransformPoint(self, other)
elif isinstance(other, NoeVec4):
return noesis.mat43TransformVec4(self, other)
else:
return NoeMat43([self.mat43[0]*other, self.mat43[1]*other, self.mat43[2]*other, self.mat43[3]*other])


I can't find the source code for
noesis.mat43Mul
.




UPDATE



Testing-out Tamas Hegedus answer:

var boneMat = new THREE.Matrix4().copy(_bone.userData.modelMatrix);

var frameMat = new THREE.Matrix4();
frameMat.set(
bone.rotationMatrix[0], bone.rotationMatrix[1], bone.rotationMatrix[2], bone.positionVector[0],
bone.rotationMatrix[3], bone.rotationMatrix[4], bone.rotationMatrix[5], bone.positionVector[1],
bone.rotationMatrix[6], bone.rotationMatrix[7], bone.rotationMatrix[8], bone.positionVector[2],
0.0, 0.0, 0.0, 1.0
);

var modelSpaceMat = new THREE.Matrix4();
modelSpaceMat.multiplyMatrices(boneMat, frameMatrix);

console.log(boneMat, frameMat, modelSpaceMat);


But the result of this
modelSpaceMat
is a bit different to
modelSpaceMat
of the python library. Like the position part which is
(-1.1457012760729413e-07, 30.441999435424805, 9.592490357590577e-08)
in python but is
3.863013744354248, 30.815059661865234, -7.705572128295898
in javascript.

Why is that?

For reference here are the outputs of the
console.log
:
enter image description here

Answer

From a mathematical point of view, you cannot multiply 4x3 matrices.

When its about affine transformations, graphics libraries use a special subset of square matrices in the homogeneous space to describe the transformation:

a b c 0
d e f 0
g h i 0
x y z 1

The last column is chosen to be 0 0 0 1 so the transformation is not a perspective projection.

Some graphics libraries only store the interesting 4x3 portion of that transformation, but multiplication must be done as it was in the 4x4 form.

Threejs has a builtin Matrix4 class, which implements multiplication.