Построение матрицы перспективной проекции - PullRequest
2 голосов
/ 21 июня 2020

мой первый пост здесь, но, надеюсь, я смогу объяснить свою дилемму с построением матрицы перспективной проекции, подобной той, что в OpenGL. Поскольку я новичок в области трехмерной графики, мне трудно понять, что делать после умножения моей матрицы после использования умножения перспективной проекции. Я пытаюсь создать это во Flutter, но это должно быть спорным вопросом, поскольку я считаю, что мое преобразование отключено.

Вот что у меня есть:

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)
     )
  );
}

И это 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;
}

Моя матрица проекции, на которую я умножаю каждую точку:

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]
];

Я считаю, что использую правильную матрицу проекции для умножения каждой векторная точка, которая у меня есть. Единственное, что после того, как я получу результат этого умножения, я не совсем уверен, что делать с результирующим вектором. Я читал о перспективном разделении, поэтому я делю значения x, y и z на четвертые, но могу ошибаться.

Любое понимание или помощь очень приветствуются. Долгое время я был в тупике, так как сам изучал это онлайн.

1 Ответ

1 голос
/ 21 июня 2020

В OpenGL матрица проекции превращается из правосторонней системы в левостороннюю. См. Правило правой руки ). Это достигается путем отражения оси z. Члены в 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]
];

Матрица перспективной проекции определяет усеченную пирамиду . Он определяет трехмерное пространство (пространство клипа), которое проецируется на двумерное окно просмотра. В OponGL вся геометрия, которая не находится в пространстве клипа, обрезается. Вы должны убедиться, что геометрия находится между ближней и дальней плоскостями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...