Reputation: 170
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:
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]
Upvotes: 0
Views: 1168
Reputation: 170
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;
}
};
Upvotes: 0
Reputation: 213688
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
Upvotes: 1