简体   繁体   English

构建透视投影矩阵

[英]Building a Perspective Projection Matrix

my first post here but hopefully I can explain my dilemma with building a perspective projection matrix similar to the one in OpenGL.我在这里的第一篇文章,但希望我可以通过构建类似于 OpenGL 中的透视投影矩阵来解释我的困境。 Being new to the 3D graphics space, I'm having trouble understanding what to do after multiplying my matrix after using a perspective projection multiplication.作为 3D 图形空间的新手,我无法理解在使用透视投影乘法后将矩阵相乘后该怎么做。 I'm attempting to create this in Flutter but it should be a moot point as I believe my conversion is off.我正在尝试在 Flutter 中创建它,但这应该是一个有争议的问题,因为我相信我的转换已经关闭。

Here is what I have:这是我所拥有的:

var center = {
  'x': size.width / 2,
  'y': size.height / 2
};

List points = [];
points.add(createVector(-50, -50, -50, center));
points.add(createVector(50, -50, -50, center));
points.add(createVector(50, 50, -50, center));
points.add(createVector(-50, 50, -50, center));
points.add(createVector(-50, -50, 50, center));
points.add(createVector(50, -50, 50, center));
points.add(createVector(50, 50, 50, center));
points.add(createVector(-50, 50, 50, center));

for (int i = 0; i < points.length; i++) {
  var matrix = matmul(projection, points[i]);
  var w = matrix[3][0];
  projected.add(
     Offset(
        (matrix[0][0] / w), 
        (matrix[1][0] / w)
     )
  );
}

And these are the 2 custom functions I've created:这些是我创建的 2 个自定义函数:

List createVector(x, y, z, center) {
  return [
    [center['x'] + x],
    [center['y'] + y],
    [z],
    [0]
  ];
}

List matmul(a, b) {
  int colsA = a[0].length;
  int rowsA = a.length;
  int colsB = b[0].length;
  int rowsB = b.length;

  if (colsA != rowsB) {
    return null;
  }

  List result = [];
  for (int j = 0; j < rowsA; j++) {
    result.add([]);
    for (int i = 0; i < colsB; i++) {
      double sum = 0.0;
      for (int n = 0; n < colsA; n++) {
        sum += a[j][n] * b[n][i];
      }
      result[j].add(sum);
    }
  }
  
  return result;
}

My projection matrix that I'm multiplying each point with is:我将每个点乘以的投影矩阵是:

var aspect = size.width / size.height;
var fov = 100;
var near = 200;
var far = 300;

List projection = [
  [1 / (aspect * tan(fov / 2)), 0, 0, 0],
  [0, 1 / (tan(fov / 2)), 0, 0],
  [0, 0, (near + far) / (near - far), (2 * near * far) / (near - far)],
  [0, 0, -1, 0]
];

I believe I am using the correct projection matrix to multiply each vector point that I have.我相信我正在使用正确的投影矩阵来乘以我拥有的每个矢量点。 The only thing is, after I get the result from this multiplication, I'm not entirely sure what to do with the resultant vector.唯一的事情是,在我得到这个乘法的结果之后,我不完全确定如何处理结果向量。 I've read about the perspective divide so I am dividing the x, y and z values by the 4th values but I could be incorrect.我已经阅读了透视除法,所以我将 x、y 和 z 值除以第 4 个值,但我可能不正确。

Any insight or help is much appreciated.非常感谢任何见解或帮助。 Have been stumped for a long time as I have been learning this online on my own.因为我自己在网上学习这个,所以我被难住了很长时间。

In OpenGL the projection matrix turns from a right handed system to a left handed system.在 OpenGL 中,投影矩阵从右手系统变为左手系统。 See Right-hand rule ).右手定则)。 This is accomplished by mirroring the z axis.这是通过镜像 z 轴来实现的。
The terms in the 3rd column have to be inverted ( - (near+far) / (near-far) respectively - (2*near*far) / (near-far) ):第 3 列中的术语必须倒置( - (near+far) / (near-far)分别- (2*near*far) / (near-far) ):

List projection = [
  [1 / (aspect * tan(fov/2)), 0, 0, 0],
  [0, 1 / (tan(fov/2)), 0, 0],
  [0, 0, - (near+far) / (near-far), - (2*near*far) / (near-far)],
  [0, 0, -1, 0]
];

The perspective projection matrix defines a Viewing frustum .透视投影矩阵定义了一个视锥体 It defines a 3 dimensional space (clip space) which is projected on the 2 dimensional viewport.它定义了投影在 2 维视口上的 3 维空间(剪辑空间)。
In OponGL all the geometry which is not in clip space is clipped.在 OponGL 中,所有不在裁剪空间中的几何图形都被裁剪。 You have to ensure that the geometry is in between the near and far plane.您必须确保几何体位于近平面和远平面之间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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