简体   繁体   中英

How to create projection matrix from forward/left/up vectors in webgl

I have webgl code that uses 3 rotation angles to rotate camera and then it returns forward, left and up vectors. It works fine:

function matrixFromPositionAndRotation(aPosition, aRotX, aRotY, aRotZ) {
    var matrix = mat4.create();
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 2000.0, matrix);

    mat4.rotateX(matrix, aRotX);
    mat4.rotateY(matrix, aRotY);
    mat4.rotateZ(matrix, aRotZ);

    mat4.translate(matrix, aPosition);

    return {
        matrix: matrix,
        forward: vec3.create([matrix[2], matrix[6], matrix[10]]),
        left: vec3.create([matrix[0], matrix[4], matrix[8]]),
        up: vec3.create([matrix[1], matrix[5], matrix[9]])
    };
}        

However I want to do the opposite. I know position, forward, left and up vectors, and I want to calculate projection matrix. I tried the opposite, but it doesn't work:

function matrixFromPositionAndVectors(aPosition, aForward, aLeft, aUp) {
    var matrix = mat4.create();
    gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 2000.0, matrix);

    mat4.translate(matrix, aPosition);

    matrix[0] = aLeft[0];
    matrix[4] = aLeft[1];
    matrix[8] = aLeft[2];

    matrix[2] = aForward[0];
    matrix[6] = aForward[1];
    matrix[10] = aForward[2];

    matrix[1] = aUp[0];
    matrix[5] = aUp[1];
    matrix[9] = aUp[2];

    return {
        matrix: matrix
    };
}     

You probably need to multiply the matrix you have by the one you're creating

    mat4.perspective(45, gl.viewportWidth / gl.viewportHeight, 0.1, 2000.0, matrix);

    mat4.translate(matrix, aPosition);

    const m = [
      ...aLeft, 0,
      ...aUp, 0,
      ...aForward, 0,
      0, 0, 0, 1,
    ];
    mat4.multiply(matrix, matrix, m);

Note though that I'd expect aLeft to actually be aRight . In other words consider the identiy

[
  1, 0, 0, 0,    // points right (x = 1)
  0, 1, 0, 0,    // points up    (y = 1)
  0, 0, 1, 0,    // points ??    (z = 1) If you define +Z as forward.
  0, 0, 0, 1,
]

For camera matrices -Z is usually forward.

I'm also guessing you're unfamiliar with WebGL (OpenGL) matrices. They call rows "columns"

[
  1, 0, 0, 0,    // column 0
  0, 1, 0, 0,    // column 1
  0, 0, 1, 0,    // column 2
  0, 0, 0, 1,    // column 3
]

And so the xAxis goes here

[
  Xx, Xy, Xz,  0,    // column 0 (xAxis)
   0,  1,  0,  0,    // column 1
   0,  0,  1,  0,    // column 2
   0,  0,  0,  1,    // column 3
]

Though of course you didn't post your math library. mat4 is not part of anything standard so without seeing it we can't know what it's doing, only guess.

you can test though. Do this

console.log(mat4.translate(mat4.create(), [11, 22, 33]));

You'll likely get

[
   1, 0, 0, 0,
   0, 1, 0, 0,
   0, 0, 1, 0,
  11,22,33, 1,
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM