关于matrix:Webgl:旋转对象沿轴变形

Webgl: Rotating object becomes distorted along axes

我在尝试以3D显示三个笛卡尔平面时遇到麻烦,当它们旋转时,这些平面在一个方向(z轴,蓝色)上拉伸,而在另一个方向(x轴,红色)上压缩,就像这些图像显示围绕y旋转一样-轴:

45度:
>
</p>
<p>
95度:<br />
<img src=

135度:
enter image description here

我使用gl-matrix库中的mat4.perspective计算透视矩阵:

1
mat4.perspective(this.pMatrix_, this.vFieldOfView_, this.aspect_, this.near_, this.far_);

值为:

1
2
3
private near_ = 0.1;
private far_ = 1000.0;
private vFieldOfView_ = 60.0 * Math.PI / 180;

顶点着色器:

1
2
3
void main(void) {
    gl_Position = uProjection * uView * uTransform * vec4(aVertexPosition, 1.0);
}

视图矩阵将对象从相机平移了2.0个单位。

1
2
3
4
let t = new Mat4();
t.array[12] = v.x;
t.array[13] = v.y;
t.array[14] = v.z;

我使用此代码生成的矩阵绕y轴旋转平面:

1
2
3
4
5
6
// identity matrix already set
let rad = angle * Math.PI / 180;
r.array[0] = Math.cos(rad);
r.array[2] = Math.sin(rad);
r.array[8] = -1.0 * Math.sin(rad);
r.array[10] = Math.cos(rad);

然后按此顺序将对象的三个变换矩阵相乘:
旋转*平移*比例。曾经使用四元数来处理旋转,但是它们同样发生了扭曲,因此回到了使用旋转矩阵并保持旋转简单的一个轴上。看来我执行的乘法步骤顺序错误,或者未正确使用透视矩阵或符号错误。

更新:

只是为了阐明顶点着色器中某些矩阵的值:

uProjection = pMatrix_ =从??mat.perspective(...)获得的值。

uView = [1、0、0、0、0、1、0、0、0、0、1,-2.0、0、0、0、1],即矩阵在z轴上平移了2个单位。

在此示例中,uTransform应该是身份矩阵。

更新2:

uView实际上是[1、0、0、0、0、1、0、0、0、0、1、0、0、0,-2.0、1]


您已经调换了视图矩阵。 你有

1
2
3
4
1  0  0  0
0  1  0  0
0  0  1  0
0  0 -2  1

你要:

1
2
3
4
1  0  0  0
0  1  0  0
0  0  1 -2
0  0  0  1

如果仅使用gl-matrix并使用mat4.translate(),则永远不会发生此错误。 这就是为什么我不使用直接数组访问来创建矩阵的原因,太容易搞砸了。

请记住,OpenGL矩阵像列向量数组一样存储。 因此索引如下所示:

1
2
3
4
 0  4  8 12
 1  5  9 13
 2  6 10 14
 3  7 11 15


我发现实现的地方出了问题,那就是矩阵乘法。 正确的代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
static multiply(a: Mat4, b: Mat4, out: Mat4) {

    let a11 = a.array[0], a12 = a.array[1], a13 = a.array[2], a14 = a.array[3],
        a21 = a.array[4], a22 = a.array[5], a23 = a.array[6], a24 = a.array[7],
        a31 = a.array[8], a32 = a.array[9], a33 = a.array[10], a34 = a.array[11],
        a41 = a.array[12], a42 = a.array[13], a43 = a.array[14], a44 = a.array[15];

    for (let i = 0; i < 16; i += 4) {
        let b1 = b.array[i], b2 = b.array[i + 1], b3 = b.array[i + 2], b4 = b.array[i + 3];
        out.array[i] = b1 * a11 + b2 * a21 + b3 * a31 + b4 * a41;
        out.array[i + 1] = b1 * a12 + b2 * a22 + b3 * a32 + b4 * a42;
        out.array[i + 2] = b1 * a13 + b2 * a23 + b3 * a33 + b4 * a43;
        out.array[i + 3] = b1 * a14 + b2 * a24 + b3 * a34 + b4 * a44;
    }
};