Исчисление плоскости усеченного конуса - PullRequest
6 голосов
/ 11 сентября 2011

Я пишу простой движок JavaScript 3D с нуля, используя Canvas и box-like примитивы (а-ля Minecraft). Я внедряю как можно больше оптимизаций, и пока у меня есть отбор спины и скрытая окклюзия лица, но я не могу понять, как сделать обрезку усеченного конуса оптимальным способом.

Я пробовал 2D отбраковку, но у меня есть одна конкретная проблема, которую я не могу решить: если одна вершина плоскости из 4 точек проходит за камерой, она все еще рисуется, но полностью искажается (координаты x и y меняются местами). Я думаю) - см. Изображение.

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

At first everything's ok

enter image description here

Я пытался ограничить координаты x и y вершин внутри 2D-экрана, пока хотя бы одна из 4 вершин все еще находится внутри экрана (см. Ниже), но это полностью искажает квадратную грань (хотя я предполагаю, Я могу пойти с более причудливой математикой и дополнительными треугольниками).

enter image description here

У меня есть некоторый опыт работы с OpenGL, и он отображает вещи совершенно по-другому, так что это даже не проблема.

Есть ли у меня шанс исправить это, не дергая себя за волосы?


Решение

Окончательное решение состояло в том, чтобы проверить каждую из 8 вершин относительно ближней плоскости отсечения в 3D перед тем, как выполнить 2D-проекцию, а затем вырезать экран.

Это второй шаг отсечения, первый - проверить, находится ли прямоугольник полностью за плоскостью отсечения, используя ограничивающую сферу радиуса sqrt(3/2)*boxSideLength.

Дополнительные треугольники (на самом деле точки в этом случае) были слишком сложными и математически сложными, это решение не идеальное, но довольно симпатичное.

Ответы [ 2 ]

4 голосов
/ 11 сентября 2011

Вы не можете проецировать трехмерную точку, которая находится за вашей камерой, на 2-мерное пространство экрана, и это не имеет никакого смысла. так что вам нужно определить, по крайней мере, ближнюю плоскость, к которой нужно привязать. После того, как вы трансформируете точки из мирового пространства в пространство камеры, но перед тем, как проецировать на пространство экрана, вам нужно будет сделать некоторые отсечения. Вы захотите определить ближнюю плоскость, что-то вроде z = 1 или что-то близкое, но перед камерой, и вы определите пространство, где точки могут проецироваться в пространство экрана.

У вас есть три варианта, во-первых, если какая-либо точка в многоугольнике отстает от ближней плоскости, тогда не рисуйте весь многоугольник. Это просто, но обычно недопустимо. Сравните каждую точку с ближней плоскостью (если polygon.points[i].z < near.z). Но это заставит многоугольники исчезать и появляться, казалось бы, случайно на краях экрана.

Ваш второй вариант - обрезать полигон до ближайшей плоскости. Для треугольников, если все три точки находятся за ближней плоскостью, не рисуйте. Если две точки позади, обрежьте два отрезка линии в ближней плоскости и нарисуйте треугольник. Если одна точка находится за ближней плоскостью, то обрежьте и сделайте два новых треугольника и нарисуйте. Если никто не находится за ближней плоскостью, тогда просто нарисуйте. Если бы я не публиковал это со своего телефона, я бы углубился в детали, но, надеюсь, это имеет смысл.

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

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

1 голос
/ 11 сентября 2011

Посмотрите на отсечение . Коэн-Сазерленд - это довольно простой в использовании метод.На странице википедии, на которую есть ссылки, даже есть некоторый код на C / C ++ для его реализации.

Если вы представите такие вещи, как затенение Гуро и наложение текстуры, вы обнаружите отсечение после того, как разделитель w будет все еще значительно искажать вещи (то есть текстура ицветовая интерполяция будет выглядеть неправильно).Поэтому мне часто лучше делать что-то вроде Коэна-Сазерленда в 3D.

...