[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] Re: Get Viewport for converting coordinates



The size the canvas is rendered to is independent of the size it is displayed at.

<cavnas width="100" height="100" style="width: 300px; height: 400px"></canvas>

Will create a canvas that renders to a 100x100 pixel backbuffer but is stretched and displayed at 300x400 pixels so you should use the size it's displayed at to do your projection and click computations.

Assuming you are doing standard world * view * projection math for your models here's how you should calculate the correct projection for your projection matrix based on the size the backbuffer is displayed

    perspective(
        projection,
        angleInRadians,
        canvas.clientWidth / canvas.clientHeight,
        zNear,
        zFar);

And here is converting a place you click on the canvas into a ray that goes through the world.

function clientPositionToWorldRay(
    mouseXPosition,
    mouseYPosition) {
  // normScreenX, normScreenY are in frustum coordinates.
  var normScreenX = mouseXPosition / (canvas.width * 0.5) - 1;
  var normScreenY = -(mouseYPosition / (canvas.height * 0.5) - 1);

  // Apply inverse view-projection matrix to get the ray in world coordinates.
  return {
      near: transformPoint(
          viewProjectionInverse, [normScreenX, normScreenY, 0]),
      far: transformPoint(
          viewProjectionInverse, [normScreenX, normScreenY, 1])
  };
};

here are the definitions of the functions referenced above

function perspective(angle, aspect, near, far) {
  var f = Math.tan(0.5 * (Math.PI - angle));
  var range = near - far;

  return [
    f / aspect, 0, 0, 0,
    0, f, 0, 0,
    0, 0, far / range, -1,
    0, 0, near * far / range, 0
  ];
};

function transformPoint(m, v) {
  var v0 = v[0];
  var v1 = v[1];
  var v2 = v[2];
  var d = v0 * m[0*4+3] + v1 * m[1*4+3] + v2 * m[2*4+3] + m[3*4+3];
  return [(v0 * m[0*4+0] + v1 * m[1*4+0] + v2 * m[2*4+0] + m[3*4+0]) / d,
          (v0 * m[0*4+1] + v1 * m[1*4+1] + v2 * m[2*4+1] + m[3*4+1]) / d,
          (v0 * m[0*4+2] + v1 * m[1*4+2] + v2 * m[2*4+2] + m[3*4+2]) / d];
};

If you need code for viewProjectionInverse I can post that as well.