Webgl:旋转对象沿轴

时间:2016-04-22 20:25:11

标签: matrix 3d rotation webgl

我无法尝试在3D中显示三个笛卡尔平面,当它们旋转时,平面会在一个方向上拉伸(z轴,蓝色)并在另一个方向上压缩(x轴,红色),就像这些图像一样显示围绕y轴的旋转:

45度:

95度:
enter image description here

135度: enter image description here

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

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

值为:

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

顶点着色器:

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

视图矩阵将对象2.0单位转换为远离相机。

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

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

// 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,0.0,0,0,0,1]即矩阵在z轴上平移2个单位。

在这个例子中,uTransform应该是单位矩阵。

UPDATE2:

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

2 个答案:

答案 0 :(得分:1)

您已转置了视图矩阵。

1  0  0  0
0  1  0  0
0  0  1  0
0  0 -2  1

你想:

1  0  0  0
0  1  0  0
0  0  1 -2
0  0  0  1

如果你只是坚持使用gl-matrix并使用mat4.translate(),那么这个错误永远不会发生。这就是为什么我不使用直接阵列访问来创建矩阵的原因,它很容易搞砸。

请记住,OpenGL矩阵的存储方式类似于列向量。所以索引是这样的:

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

答案 1 :(得分:0)

我发现我的实现出错了,就是矩阵乘法。正确的代码是:

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