gl-matrix icon indicating copy to clipboard operation
gl-matrix copied to clipboard

Mat4 perspective function wrong coordinate system.

Open kujukuju opened this issue 10 years ago • 8 comments

When you call mat4.perspective with the out matrix being your projection matrix your coordinate system gets flipped to left handed.

I used mat4.frustum to get around this issue and maintain a right handed coordinate system.

kujukuju avatar Mar 25 '15 00:03 kujukuju

Having the same confusion. Is this done on purpose?

toruta39 avatar Apr 06 '15 14:04 toruta39

I don't think it's on purpose because I have no idea why they would decide to switch OpenGLs default coordinate system.

But regardless their ortho function still works properly so here is my workaround: this.perspectiveGL = function(out, fovY, aspect, zNear, zFar) { var PI = 3.1415926535897932384626433832795; var fW, fH; fH = Math.tan(fovY / 360 * PI) * zNear; fW = fH * aspect; mat4.frustum(out, -fW, fW, -fH, fH, zNear, zFar); };

kujukuju avatar Apr 06 '15 17:04 kujukuju

Er sorry, I meant their frustum method still works properly... But ya ortho works too.

kujukuju avatar Apr 06 '15 17:04 kujukuju

In 0.9.5 the code was like this:

/*
 * mat4.frustum
 * Generates a frustum matrix with the given bounds
 *
 * Params:
 * left, right - scalar, left and right bounds of the frustum
 * bottom, top - scalar, bottom and top bounds of the frustum
 * near, far - scalar, near and far bounds of the frustum
 * dest - Optional, mat4 frustum matrix will be written into
 *
 * Returns:
 * dest if specified, a new mat4 otherwise
 */
mat4.frustum = function(left, right, bottom, top, near, far, dest) {
    if(!dest) { dest = mat4.create(); }
    var rl = (right - left);
    var tb = (top - bottom);
    var fn = (far - near);
    dest[0] = (near*2) / rl;
    dest[1] = 0;
    dest[2] = 0;
    dest[3] = 0;
    dest[4] = 0;
    dest[5] = (near*2) / tb;
    dest[6] = 0;
    dest[7] = 0;
    dest[8] = (right + left) / rl;
    dest[9] = (top + bottom) / tb;
    dest[10] = -(far + near) / fn;
    dest[11] = -1;
    dest[12] = 0;
    dest[13] = 0;
    dest[14] = -(far*near*2) / fn;
    dest[15] = 0;
    return dest;
};

/*
 * mat4.perspective
 * Generates a perspective projection matrix with the given bounds
 *
 * Params:
 * fovy - scalar, vertical field of view
 * aspect - scalar, aspect ratio. typically viewport width/height
 * near, far - scalar, near and far bounds of the frustum
 * dest - Optional, mat4 frustum matrix will be written into
 *
 * Returns:
 * dest if specified, a new mat4 otherwise
 */
mat4.perspective = function(fovy, aspect, near, far, dest) {
    var top = near*Math.tan(fovy*Math.PI / 360.0);
    var right = top*aspect;
    return mat4.frustum(-right, right, -top, top, near, far, dest);
};

I'm still learning the math though, so I'll post if I notice anything wrong.

trusktr avatar Apr 12 '15 06:04 trusktr

Have a read of http://stackoverflow.com/a/12336360/868679

OpenGL is left-handed at the end of the pipeline.

BrendanAnnable avatar Jun 04 '15 05:06 BrendanAnnable

Is this still an issue?

stefnotch avatar Apr 25 '18 16:04 stefnotch

You can flip it back using

matrix[10] = -matrix[10]
matrix[14] = -matrix[14]

Pyrolistical avatar Aug 03 '18 08:08 Pyrolistical

@stefnotch it should be documented in my opinion.

in other cases, the DirectX util has both (D3DXMatrixPerspectiveFovLH & D3DXMatrixPerspectiveFovRH).

pmingkr avatar Jun 01 '23 06:06 pmingkr