Какое лицо дальше в параллельных проекциях? - PullRequest
0 голосов
/ 02 октября 2018

Я работаю с JavaScript (React) над геометрической программой , которая создает аксонометрию (лучше параллельные проекции) указанный объект определен по вершинам и граням (грань может иметь разное количество вершин).

enter image description here

Отлично работает, если вы не нужно, чтобы грани были непрозрачными в противном случае есть грани выше других, которые должны быть ниже.

Поэтому я хочу заказать свой список лиц от дальнейших к ближайшим :

[
[[100, 0, 100], [50, 50, 50], [120, 170, 120], [10, 200, 150]],
[[10, 20, 30], [10, 200, 250], [50, 50, 50], [100, 30, 30]],...
]

Я буду использовать faces.sort(sortingFunction).

Меня не волнует пересечение граней

(это объединит грани всех объектов)

Каким должен быть sortingFunction?

Вы должны рассмотреть как определяется аксонометрия .Это определяется X-, осью Y вращения (Вращение может быть как большим, так и меньшим, чем вращением), Z вращением является π / 4 (90 °) .

Вот старая версия приложения , которая поможет вам понять, что я имею в виду: http://dev_proiezioni.surge.sh/

Извините за мой ужасный английский.Спасибо

Ответы [ 4 ]

0 голосов
/ 02 октября 2018

То, что вы пытаетесь сделать, называется «отбором задних граней». Один из распространенных методов - определить, располагаются ли списки точек в представлении многоугольника по часовой стрелке или против часовой стрелки с точки зрения камеры.Это требует, чтобы вы были очень осторожны при создании списка вершин.Для получения более подробной информации ознакомьтесь со статьей в Википедии: https://en.wikipedia.org/wiki/Back-face_culling. В разделе «Реализация» описывается математика, которую вам нужно будет перевести на JavaScript.Этот метод быстрее, чем сортировка списка лиц, поскольку он требует проверки каждого лица только один раз, а не сравнения каждого лица с другими лицами.

0 голосов
/ 02 октября 2018

Мне нет дела до пересечения граней

Это означает, что мы можем уменьшить равнины до точек, взяв точку в середине:

const vecOp = op => (a, b) => a.map((c, i) => op(c,  b[i] || b));

const add = vecOp((a, b) => a + b);
const sub = vecOp((a, b) => a - b);
const mul = vecOp((a, b) => a * b);
const div = vecOp((a, b) => a / b);
 const sum = v => v.reduce((a, b) => a + b, 0);

const middle = (a, b) =>  div(add(a, b), 2);

 const planeToPoint = ([a, b, c, d]) => middle(
   middle(a, b),
   middle(c, d)
 );

Теперь, чтобы отсортировать по «ближе к камере», можно провести линию между центрами двух плоскостей, что приведет к направлению:

 const aToB = (a, b) => 
   sub(
    planeToPoint(b),
    planeToPoint(a)
  );

Теперь мы можем превратить вращение камеры ввзгляд камеры на вектор :

 const rotToVec = (yaw, pitch) => ([
   Math.cos(yaw) * Math.cos(pitch),
   Math.sin(yaw) * Math.cos(pitch),
   Math.sin(pitch)
 ]);

, и это направление можно сравнить с направлением камеры, что дает угол между ними:

 const angle = (a, b) => sum(mul(a, b)) / sum(a) * sum(b)

Теперь давайте повернем это все вместе:

 const camVec = rotToVec(cam.yaw, cam.pitch);

 planes.sort((a, b) =>
  Math.abs(angle(aToB(a, b), camVec)) < Math.PI / 4 /*90°*/ ? 1 : -1
 );

Отказ от ответственности: я не пробовал приведенный выше код, не работал с параллельными проекциями и не разбираюсь в математике, поэтому будьте осторожны со своими словами, я понятия не имею, что яговорить о

0 голосов
/ 02 октября 2018

Для приблизительного решения используйте преобразование 3D в 3D и рассмотрите координату Z.Для каждого лица сохраняйте ближайшее Z и сортируйте грани этого Z.

Для более точного решения рассмотрите https://en.wikipedia.org/wiki/Newell%27s_algorithm.

0 голосов
/ 02 октября 2018

Сортировка по расстоянию от камеры.

function distanceBetweenTwoPoints (p1, p2) {
  return Math.hypot(p1.x - p2.x, p1.y - p2.y, p1.z - p2.z)
}

function sortFunction (p1, p2) {
  return distanceBetweenTwoPoints(camera, p1) > distanceBetweenTwoPoints(camera,p2) ? -1 : 1
}

Настройте знак > в зависимости от того, какой порядок вы хотите.

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