在JavaScript中乘以4x3仿射变换矩阵 [英] Multiplying 4x3 affine transform matrices in javascript

查看:116
本文介绍了在JavaScript中乘以4x3仿射变换矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Three.JS中计算转换,说实话,我是3D数学的新手.

Three.JS中有3x3和4x4矩阵类,但没有4x3.

目标:我想了解如何在4x3 * 4x3矩阵上进行乘法.

我有一组输入和正确的输出.我通过使用python来获得它,因为有一个名为Noesis的库,该库具有4x3矩阵的乘法.

问题在于该库是从python二进制文件中调用的,所以我看不到源代码.

python中的代码很简单:modelSpaceMat = boneMat * frameMat

以下是正确数据集的示例:

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)
)

现在,我希望能够使用javascript做到这一点.

问题:

  • 有可用的图书馆吗?
  • 什么是公式?

python模块 Noesis 具有以下内容: :

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])

我找不到noesis.mat43Mul的源代码.


更新

正在测试 Tamas Hegedus 答案:

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);

但是此modelSpaceMat的结果与python库的modelSpaceMat有点不同.就像位置部分在python中是(-1.1457012760729413e-07, 30.441999435424805, 9.592490357590577e-08)但在javascript中是3.863013744354248, 30.815059661865234, -7.705572128295898.

那是为什么?

作为参考,以下是console.log的输出:

解决方案

从数学的角度来看,您不能将4x3矩阵相乘.

当涉及仿射变换时,图形库在齐次空间中使用特殊的平方矩阵子集来描述该变换:

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

最后一列被选择为0 0 0 1,因此变换不是透视投影.

某些图形库仅存储该转换的有趣的4x3部分,但是必须像4x4形式那样进行乘法.

Threejs具有内置的 Matrix4 类,该类实现乘法. /p>

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:

解决方案

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.

这篇关于在JavaScript中乘以4x3仿射变换矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆