0
votes

I'm having trouble trying to display three cartesian planes in 3D, when they rotate the planes get stretched in one direction (z-axis, blue) and compressed in another (x-axis, red) like these images showing rotation around the y-axis:

45 degrees:

95 degrees:
enter image description here

135 degrees: enter image description here

I calculate the perspective matrix, with mat4.perspective from the gl-matrix library:

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

with values of:

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

Vertex Shader:

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

The view matrix translates the object 2.0 units away from the camera.

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

I rotate the planes around the y-axis using the matrix generated from this code:

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

And I multiply the three transform matrices of the object in this order: rotation * translation * scale. Was using quaternions to handle rotations but they were similarly distorted so went back to using rotation matrices and kept the rotation simple, in one axis. It looks like I'm doing some multiplication step in the wrong order or not using the perspective matrix correctly or got a sign wrong.

Update:

Just to clarify on the value of some of the matrices in vertex shader:

uProjection = pMatrix_ = value obtained from mat.perspective(...).

uView = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, -2.0, 0, 0, 0, 1] i.e. matrix translated 2 units away in z-axis.

uTransform should be identity matrix in this example.

Update2:

uView was actually [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, -2.0, 1]

2
Why new Mat4() instead of mat4.create(), if you are using the gl-matrix library?Dietrich Epp
Since you have the matrixes separate like that, it might be helpful to show us the value of each matrix. It looks like a sign may have gotten flipped somewhere, which is why I usually stick to existing math libraries like gl-matrix instead of direct array access.Dietrich Epp
Working in typescript and have a Mat4 class to make type checking easier, which is basically just a Float32Array(16) with assessors. Use gl-matrix to do calculations like the perspective matrix.dppower
But apparently, you're not using functions like mat4.rotateY() or mat4.translate(), which would make this so much easier.Dietrich Epp

2 Answers

1
votes

You have transposed your view matrix. You have

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

You want:

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

This mistake never would have happened if you just stuck with gl-matrix and used mat4.translate(). This is why I don't use direct array access for creating a matrix, it's too easy to screw up.

Remember that OpenGL matrixes are stored like an array of column vectors. So the indexes go like this:

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

I found out where I was going wrong with my implementation, it was with the matrix multiplication. The correct code is this:

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