Геометрия на авто в векторе

Содержание

Как проверить геометрию кузова автомобиля

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

kuzov 1

Содержание

Что такое геометрия кузова

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

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

Где проверить геометрию кузова

kuzov 2

Существует несколько способов обнаружить деформацию кузовных элементов подержанной машины. Это можно сделать:

Рассмотрим подробно каждый из перечисленных выше вариантов.

Проверяем геометрию кузова самостоятельно

Это можно сделать как по косвенным внешним признакам, так и при помощи специальных измерительных инструментов. Предварительно закрываем двери, а также крышки капота и багажного отделения авто. При этом смотрим, насколько легко удастся выполнить данные действия. Если при закрывании возникли трудности – это уже признак того, что у кузова машины нарушена геометрия (например, проблемы с захлопыванием дверей могут быть вызваны деформацией стоек).

Визуальный осмотр

Сначала проверяем стекла. Присутствие горизонтальных трещин – один из признаков нарушения геометрии кузова. Затем, присев на корточки, внимательно осматриваем корпус автомобиля. Смотреть нужно вдоль борта: так лучше заметны неровности и зазоры между кузовными элементами, которые также могут свидетельствовать о нарушении геометрии. Затем переходим к замерам.

Проверка геометрии кузова специальными инструментами

geometria min

Нам потребуется особый штангенциркуль и масштабная рейка. Первый необходим для проверки правильности расположения колес относительно друг друга. Также он подходит для сравнения месторасположения контрольных точек на разных сторонах кузова ТС.

Сначала измеряем расстояние между двумя точками с одной стороны. Затем фиксируем положение ножек циркуля при помощи специального крепежа. Далее проводим замеры между аналогичными контрольными точками с другой стороны кузова. Если результаты не совпадают – геометрия нарушена.

По такому же принципу можно проверить наличие деформации кузова при помощи масштабной рейки. Она имеет телескопическую конструкцию и регулируемые по высоте указатели, что дает возможность проводить замеры при наличии между контрольными точками различных препятствий. Также масштабная рейка позволяет рассчитать точное расстояние между контрольными точками на кузове и раме ТС и сравнить их с данными, указанными производителем авто.

Как проверить геометрию кузова обычной рулеткой

ruletka

Она менее точна, но общее представление о нарушении геометрии кузова транспортного средства с ее помощью получить можно. Прежде всего, проверяем переднюю колею: измеряем расстояние от середины протектора переднего левого колеса до середины протектора правого переднего колеса. Затем таким же образом выполняем проверку задней колеи. Сверяем полученные данные с информацией завода-изготовителя. Несоответствие результатов послужит доказательством того, что геометрия кузова авто нарушена. Аналогичным образом проверяем длину колесной базы (замеры производим между центром ступицы переднего колеса и центром ступицы заднего колеса). Также, используя обычную рулетку, проверяем:

Существует еще один достаточно простой способ проверить геометрию кузова ТС. Для этого на ровной и прямой дороге разгоняем авто и на несколько секунд отпускаем рулевое колесо. Если машину начнет уводить в сторону – возможны проблемы с геометрией кузова. Для получения более точного результата проверить машину нужно при разной скорости движения – 50 и 90 км/час.

Проверяем геометрию кузова в автосервисе

mceclip4(1)

Специализированные техцентры используют для обнаружения деформаций современное компьютерное оборудование. Автомобиль частично разбирают и помещают на специальный стенд. На контрольные точки крепят электронные датчики. Показания передаются на компьютер, который создает некую трехмерную модель ТС и сравнивает изначальные данные с информацией, полученной в ходе проверки.

К преимуществам такого способа относят высокую точность измерений. Среди недостатков: временные и финансовые затраты. Проверка геометрии кузова на специальном стенде обойдется владельцу в несколько тысяч рублей. Тем не менее, эксперты рекомендуют владельцам проверять ТС подобным образом не реже 1 раза в 12 месяцев, аргументируя это тем, что причиной деформации кузова может стать не только ДТП, но и обычная езда по разбитым российским дорогам.

О чем следует помнить

Если перед покупкой транспортного средства нарушений геометрии кузовных элементов выявлено не было, это не значит, что машина не побывала в серьезной аварии. Возможно, ее просто качественно отремонтировали. Однако даже если восстановление битого авто выполнено на должном уровне – оно уже не является на 100 процентов надежным в эксплуатации. Поэтому чтобы убедиться в том, что вы не покупаете кота в мешке – воспользуйтесь еще одним простым и доступным способом проверки ТС на сайте Автокод. Он подходит для тех, кому нужна одна или несколько проверок автомобилей.

Автокод поможет косвенно проверить геометрию кузова авто. Для этого достаточно ввести в поле поиска гос номер или ВИН-код ТС. Через несколько минут система выдаст отчет с подробной историей подержанной машины. Если вас, прежде всего, интересует информация о геометрии кузова – обратите внимание на раздел, посвященный участию авто в аварии. Там размещены данные о дате происшествия, регионе, где оно произошло, типе ДТП (например, столкновение), а также схема повреждений, которые при этом получил автомобиль.

mceclip0

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

Данные об участии ТС в дорожно-транспортных происшествиях поступают на сервис непосредственно из ГИБДД, поэтому им можно полностью доверять.

Кроме того, при помощи интернет-сервиса Автокод перед покупкой вы легко проверите количество бывших владельцев ТС, пробег авто, наличие ограничений ГИБДД (арест, залог и т. п.) и получите другую информацию о подержанной машине.

Если вам нужно постоянно проверять большое количество автомобилей, воспользуйтесь сервисом «Автокод Профи». Используя сервис, вы сможете добавлять комментарии к отчетам, создавать свои списки ликвидных ТС, быстро сравнивать варианты и хранить данные об автомобилях в упорядоченном виде. Подписка на безлимитные проверки авто стоит 2 500 рублей в месяц.

Получив онлайн-отчеты, проведите качественные осмотры авто. Если вы не уверены в своих знаниях и желаете доверить осмотр профессионалу, воспользуйтесь услугами выездной проверки. Мастер приедет на место и проведет диагностику с помощью специального оборудования, а затем выдаст полное профессиональное заключение.

Источник

бесплатных Автомобиль векторов

На этой странице вы можете найти и скачать бесплатно Автомобиль векторов для фонарика вашего дизайна.

Все нижеприведенные Автомобиль векторы и пнг доступны в формате ai и eps.

бесплатных Автомобиль векторов

1257d6824a70e79

1656fa8fbc23da9

efd62c31c520f92d985f793d5992f153

Гран Торино ретро синий

1057826efdb4355

8826583ef2eb9be2d856815fe4afe9e0

1157d505ccb1d4c

0056a0d68a38baa

8e1ccc3609024d5db64dbbf0a6fcb949

ретро Гран Торино вектор

93dde8c92826e575761d9457a440d2d4

вектор мультфильм автомобиль

1757dcde566e3e8

вектор проекта конкретных машину машину

Простой желтый автомобиль мультяшный дизайн

вектор Гран Торино

спорт музыка автомобильной плакаты материал

вектор автомобильной печать

мультфильм хао машину хвост

вектор мультфильм с видом на черный автомобиль

вектор росписью автомобиля

изысканный автомобильных запчастей

гоночный автомобиль седан сбоку

автомобиль силуэт вектор

красный автомобиль мультфильм

Поездки туристических поездок на автомобиле

мультфильм вектор красный автомобиль

красный мультфильм машина

мультфильм одноместный автомобиль

реалистично текстуры Гран Торино вектор

синий черный полицейская машина

2 5d автобус общественного транспорта доступен для коммерческих элементов

работники автосервиса png

2 5d крытый желтый внедорожный джип с багажником

Желтая машина Мультяшный автомобиль Классическая машина Автомобильная иллюстрация

красный автомобиль мультфильм автомобиль детский игрушечный автомобиль автомобиль

автомобиль с видом на рис

вектор колбаса еда грузовик

расписные машину автомобилей мини автомобиль

прицеп грузовик toon

вид с передней фары автомобиля контур

мультфильм вектор купе

На этой странице вы можете найти и скачать бесплатно Автомобиль векторов для фонарика вашего дизайна.

Все нижеприведенные Автомобиль векторы и пнг доступны в формате ai и eps.

Присоединяйтесь к команде проектантов pngtree

Загрузите свой первый дизайн, защищенный авторским правом. Получите дизайнерские купоны на 5 долларов

Добро пожаловать в Pngtree

Войдите, чтобы скачать бесплатно

Отлично, чтобы ты вернулся!

Войдите, чтобы увидеть больше

создавая аккаунт я согласен с pngtree’s Условия обслуживания,

Скачать бесплатно в мире коммерческие ресурсы в мире

Зарегистрируйтесь, чтобы увидеть больше

Добро пожаловать в Pngtree, чтобы найти более креативный дизайн

Начните бесплатный пробный период

создавая аккаунт я согласен с pngtree’s Условия обслуживания,

Спасибо!

Войдите, чтобы начать скачать

усердно работать такая честь.

Почему бы не попробовать это? 2 Минута Сначала отдохни, затем продолжите загрузку позже.

Вы достигли предела загрузки 200 на сегодня.

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

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

Пожалуйста, заполните идентификационную информацию, необходимую для подтверждения вашей операции.

Источник

Основы компьютерной геометрии. Написание простого 3D-рендера

Привет меня зовут Давид, а вот я собственной персоной отрендеренный своим самописным рендером:

image loader

С развитием шейдерных языков и увеличением мощностей GPU все больше людей заинтересовались программированием графики. Появились новые направления, такие как например Ray marching со стремительным ростом своей популярности.

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

Выбор языка изначально падал на c++ или rust, но я остановился на c# из-за простоты написания кода и широких возможностей для оптимизации. Итоговым продуктом данной статьи будет рендер, способный выдавать подобные картинки:

image loader

image loader

Все модели, использованные мной здесь, распространяются в открытом доступе, не занимайтесь пиратством и уважайте труд художников!

Математика

Само собой куда же писать рендеры без понимания их математических основ. В этом разделе я изложу только те концепции, которые я использовал в коде. Тем кто не уверен в своих знаниях пропускать данный раздел не советую, без понимания этих основ трудно будет понять дальнейшее изложение. Так же я рассчитываю, что тот кто решил изучать computation geometry будет иметь базовые знания в линейной алгебре, геометрии, а так же тригонометрии(углы, вектора, матрицы, скалярное произведение). Для тех кто хочет понять вычислительную геометрию глубже, могу порекомендовать книгу Е. Никулина «Компьютерная геометрия и алгоритмы машинной графики».

Повороты вектора. Матрица поворота

Поворот — это одно из основных линейных преобразований векторного пространства. Так же оно является еще и ортогональным преобразованием, так как сохраняет длины преобразованных векторов. В двумерном пространстве существует два типа поворотов:

Давайте выведем формулы для вращения вектора в двумерном пространстве. Обозначим координаты исходного вектора — . Координаты нового вектора, повернутого на угол f, обозначим как .

image loader

Мы знаем, что длина у этих векторов общая и поэтому можем использовать понятия косинуса и синуса для того, чтобы выразить эти вектора через длину и угол относительно оси OX:

image loader

Заметьте, что мы можем использовать формулы косинуса и синуса суммы для того, чтобы разложить значения x’ и y’. Для тех, кто подзабыл я напомню эти формулы:

image loader

Разложив координаты повернутого вектора через них получим:

image loader

Здесь нетрудно заметить, что множители l * cos a и l * sin a – это координаты исходного вектора: x = l * cos a, y = l * sin a. Заменим их на x и y:

image loader

Таким образом мы выразили повернутый вектор через координаты исходного вектора и угол его поворота. В виде матрицы это выражение будет выглядеть так:

image loader

Умножьте и проверьте что результат эквивалентен тому, что мы вывели.

Поворот в трехмерном пространстве

Мы рассмотрели поворот в двумерном пространстве, а так же вывели матрицу для него. Теперь возникает вопрос, а как получить подобные преобразования для трех измерений? В двумерном случае мы вращали вектора на плоскости, здесь же бесконечное количество плоскостей относительно которых мы можем это сделать. Однако существует три базовых типа вращений, при помощи которых можно выразить любой поворот вектора в трехмерном пространстве — это XY, XZ, YZ вращения.

При таком повороте мы вращаем вектор относительно оси OZ координатной системы. Представьте, что вектора — это вертолётные лопасти, а ось OZ — это мачта на которой они держаться. При XY вращении вектора будут поворачиваться относительно оси OZ, как лопасти вертолета относительно мачты.

image loader

Заметьте, что при таком вращении z координаты векторов не меняются, а меняются x и x координаты — поэтому это и называется XY вращением.

image loader

Нетрудно вывести и формулы для такого вращения: z — координата остается прежней, а x и y изменяются по тем же принципам, что и в 2д вращении.

image loader

То же в виде матрицы:

image loader

Для XZ и YZ вращений все аналогично:

image loader

image loader

Проекция

Понятие проекции может варьироваться в зависимости от контекста в котором его используют. Многие, наверное, слышали про такие понятия, как проекция на плоскость или проекция на координатную ось.

В том понимании которое мы используем здесь проекция на вектор — это тоже вектор. Его координаты – точка пересечения перпендикуляра опущенного из вектора a на b с вектором b.

image loader

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

image loader

Направление вектора проекции по определению совпадает с вектором b, значит проекция определяется формулой:

image loader

Здесь мы получаем направление проекции в виде единичного вектора и умножаем его на длину проекции. Несложно понять, что результатом будет как раз-таки то, что мы ищем.

Теперь представим все через скалярное произведение:

image loader

Получаем удобную формулу для нахождения проекции:

image loader

Системы координат. Базисы

Многие привыкли работать в стандартной системе координат XYZ, в ней любые 2 оси будут перпендикулярны друг другу, а координатные оси можно представить в виде единичных векторов:

image loader

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

image loader

Любой вектор на плоскости можно представить в виде суммы векторов этого базиса с некими коэффициентами или же в виде линейной комбинации. Вспомните, что вы делаете когда записываете координаты вектора — вы пишете x — координату, а далее — y. Таким образом вы на самом деле определяете коэффициенты разложения по векторам базиса.

image loader

Теперь возьмём другой базис:

image loader

Через его вектора также можно представить любой 2д вектор:

image loader

А вот такой набор векторов не является базисом двухмерного пространства:

image loader

В нем два вектора и лежат на одной прямой. Какие бы их комбинации вы не брали получать будете только вектора, лежащие на общей прямой y = x. Для наших целей такие дефектные не пригодятся, однако, понимать разницу, я считаю, стоит. По определению все базисы объединяет одно свойство – ни один из векторов базиса нельзя представить в виде суммы других векторов базиса с коэффициентами или же ни один вектор базиса не является линейной комбинацией других. Вот пример набора из 3-х векторов который так же не является базисом:

image loader

Вообще любой базис n-мерного пространства будет содержать ровно n векторов, для 2д это n соответственно равно 2.

Перейдем к 3д. Трехмерный базис будет содержать в себе 3 вектора:

image loader

Если для двумерного базиса достаточно было двух векторов не лежащих на одной прямой, то в трехмерном пространстве набор векторов будет базисом если:

С данного момента базисы, с которыми мы работаем будут ортогональными (любые их вектора перпендикулярны) и нормированными (длина любого вектора базиса — 1). Другие нам просто не понадобятся. К примеру стандартный базис

image loader

удовлетворяет этим критериям.

Переход в другой базис

До сих пор мы записывали разложение вектора как сумму векторов базиса с коэффициентами:

image loader

Снова рассмотрим стандартный базис – вектор в нем можно записать так:

image loader

Как видите коэффициенты разложения вектора в базисе являются его координатами в этом базисе. Разберем следующий пример:

image loader

Этот базис получен из стандартного применением к нему XY вращения на 45 градусов. Возьмем вектор a в стандартной системе имеющий координаты

image loader

Через вектора нового базиса его можно разложить таким образом:

image loader

Если вы посчитаете эту сумму, то получите – вектор а в стандартном базисе. Исходя из этого выражения в новом базисе вектор а имеет координаты – коэффициенты разложения. Это будет виднее если взглянуть с другого ракурса:

image loader

Но как находить эти коэффициенты? Вообще универсальный метод — это решение довольно сложной системы линейных уравнений. Однако как я сказал ранее использовать мы будем только ортогональные и нормированные базисы, а для них есть весьма читерский способ. Заключается он в нахождении проекций на вектора базиса. Давайте с его помощью найдем разложение вектора a в базисе X <0.7, 0.7, 0>Y <-0.7, 0.7, 0>Z

image loader

Для начала найдем коэффициент для y’. Первым шагом мы находим проекцию вектора a на вектор y’ (как это делать я разбирал выше):

image loader

Второй шаг: делим длину найденной проекции на длину вектора y’, тем самым мы узнаем “сколько векторов y’ помещается в векторе проекции” – это число и будет коэффициентом для y’, а также y — координатой вектора a в новом базисе! Для x’ и z’ повторим аналогичные операции:

image loader

Теперь мы имеем формулы для перехода из стандартного базиса в новый:

image loader

Ну а так как мы используем только нормированные базисы и длины их векторов равны 1 отпадет необходимость делить на длину вектора в формуле перехода:

image loader

Раскроем x-координату через формулу проекции:

image loader

Заметьте, что знаменатель (x’, x’) и вектор x’ в случае нормированного базиса так же равен 1 и их можно отбросить. Получим:

image loader

Мы видим, что координата x базисе выражается как скалярное произведение (a, x’), координата y соответственно – как (a, y’), координата z – (a, z’). Теперь можно составить матрицу перехода к новым координатам:

image loader

Системы координат со смещенным центром

У всех систем координат которые мы рассмотрели выше началом координат была точка . Помимо этого существуют еще системы со смещенной точкой начала координат:

image loader

Для того, чтобы перевести вектор в такую систему нужно сначала выразить его относительно нового центра координат. Сделать это просто — вычесть из вектора этот центр. Таким образом вы как бы «передвигаете» саму систему координат к новому центу, при этом вектор остается на месте. Далее можно использовать уже знакомую нам матрицу перехода.

Пишем геометрический движок. Создание проволочного рендера.

Ну вот, думаю тому кто прошел раздел с математикой и не закрыл статью можно промывать мозги более интересными вещами! В этом разделе мы начнем писать основы 3д движка и рендеринга. Вообще рендеринг — это довольно сложная процедура, которая включает в себя много разных операций: отсечение невидимых граней, растеризация, расчет света, обработку различных эффектов, материалов(иногда даже физику). Все это мы частично разберем в дальнейшем, а сейчас мы займемся более простыми вещами — напишем проволочный рендер. Суть его в том, что он рисует объект в виде линий, соединяющих его вершины, поэтому результат выглядит похожим на сеть из проволок:

image loader

Полигональная графика

Традиционно в компьютерной графике используется полигональное представление данных трехмерных объектов. Таким образом представляются данные в форматах OBJ, 3DS, FBX и многих других. В компьютере такие данные хранятся в виде двух множеств: множество вершин и множество граней(полигонов). Каждая вершина объекта представлена своей позицией в пространстве — вектором, а каждая грань(полигон) представлена тройкой целых чисел которые являются индексами вершин данного объекта. Простейшие объекты(кубы, сферы и т.д.) состоят из таких полигонов и называются примитивами.

В нашем движке примитив будет основным объектом трехмерной геометрии — все остальные объекты будут наследоваться от него. Опишем класс примитива:

Пока все просто — есть вершины примитива и есть индексы для формирования полигонов. Теперь можно использовать этот класс чтобы создать куб:

1hbvkvvkhb3dlpsgcinc8jzzfgm

Реализуем системы координат

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

image loader

Представление объекта в локальных координатах позволяет легко производить любые операции с ним. Например, для перемещения объекта на вектор a достаточно будет сдвинуть центр его системы координат на этот вектор, для вращения объекта — повернуть его локальные координаты.

При работе с объектом мы будем производить операции с его вершинами в локальной системе координат, при рендеринге будем предварительно переводить все объекты сцены в единую систему координат — глобальную. Добавим системы координат в код. Для этого создадим объект класса Pivot (стержень, точка опоры) который будет представлять локальный базис объекта и его центральную точку. Перевод точки в систему координат представленную Pivot будет производиться в 2 шага:

Теперь используя данный класс добавим в примитивы функции вращения, передвижения и увеличения:

image loader

Вращение и перемещение объекта с помощью локальных координат

Рисование полигонов. Камера

Основным объектом сцены будет камера — с помощью нее объекты будут рисоваться на экране. Камера, как и все объекты сцены, будет иметь локальные координаты в виде объекта класса Pivot — через него мы будем двигать и вращать камеру:

image loader

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

image loader

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

image loader

Наоборот же, зная высоту дерева он может найти высоту точки на проекционной плоскости:

image loader

Теперь вернемся к нашей камере. Представьте, что к оси z координат камеры прикреплена проекционная плоскость на расстоянии z’ от начала координат. Формула такой плоскости z = z’, ее можно задать одним числом — z’. На эту плоскость падают лучи от вершин различных объектов. Попадая на плоскость луч будет оставлять на ней точку. Соединяя такие точки можно нарисовать объект.

image loader

Такая плоскость будет представлять экран. Координату проекции вершины объекта на экран будем находить в 2 этапа:

image loader

Проекция будет 2-мерным вектором, ее координаты x’ и y’ и будут определять позицию точки на экране компьютера.

Данный код имеет несколько ошибок, о исправлении которых мы поговорим далее.

Отсекаем невидимые полигоны

Спроецировав таким образом на экран три точки полигона мы получим координаты треугольника который соответствует отображению полигона на экране. Но таким образом камера будет обрабатывать любые вершины, включая те, чьи проекции выходят за область экрана, если попытаться нарисовать такую вершину велика вероятность словить ошибок. Камера так же будет обрабатывать полигоны которые находятся позади нее (координаты z их точек в локальном базисе камеры меньше z’) — такое «затылковое» зрение нам тоже ни к чему.

image loader

Для отсечения невидимых вершин в open gl используются метод усекающей пирамиды. Заключается он в задании двух плоскостей — ближней(near plane) и дальней(far plane). Все, что лежит между этими двумя плоскостями будет подлежать дальнейшей обработке. Я же использую упрощенный вариант с одной усекающей плоскостью — z’. Все вершины, лежащие позади нее будут невидимыми.

Добавим в камеру два новых поля — ширину и высоту экрана.
Теперь каждую спроецированную точку будем проверять на попадание в область экрана. Так же отсечем точки позади камеры. Если точка лежит сзади или ее проекция не попадает на экран то метод вернет точку .

Переводим в экранные координаты

Здесь я разъясню некоторый момент. Cвязан он с тем, что во многих графических библиотеках рисование происходит в экранной системе координат, в таких координатах начало — это верхняя левая точка экрана, x увеличивается при движении вправо, а y — при движении вниз. В нашей проекционной плоскости точки представлены в обычных декартовых координатах и перед отрисовкой необходимо переводить эти координаты в экранные. Сделать это нетрудно, нужно только сместить начало координат в верхний левый угол и инвертировать y:

image loader

Корректируем размер спроецированного изображения

Если вы используете предыдущий код для того, чтобы нарисовать объект то получите что-то вроде этого:

image loader

Почему — то все объекты рисуются очень маленькими. Для того, чтобы понять причину вспомните как мы вычисляли проекцию — умножали x и y координаты на дельту отношения z’ / z. Это значит, что размер объекта на экране зависит от расстояния до проекционной плоскости z’. А ведь z’ мы можем задать сколь угодно маленьким значением. Значит нам нужно корректировать размер проекции в зависимости от текущего значения z’. Для этого добавим в камеру еще одно поле — угол ее обзора.

image loader

image loader

Вот такой простой код отрисовки я использовал для теста:

Давайте проверим рендер на сцене и кубов:

image loader

И да, все прекрасно работает. Для тех, кому разноцветные кубики не кажутся пафосными я написал функцию парсинга моделей формата OBJ в объекты типа Primitive, залил фон черным и отрисовал несколько моделей:

image loader

image loader

Растеризация полигонов. Наводим красоту.

В прошлом разделе мы написали проволочный рендер. Теперь мы займемся его модернизацией — реализуем растеризацию полигонов.

По простому растеризировать полигон — это значит закрасить его. Казалось бы зачем писать велосипед, когда есть уже готовые функции растеризации треугольника. Вот что будет если нарисовать все дефолтными инструментами:

image loader

Современное искусство, полигоны сзади нарисовались поверх передних, одним словом — каша. К тому же как таким образом текстурировать объекты? Да, никак. Значит нам нужно написать свой имба-растерайзер, который будет уметь в отсечение невидимых точек, текстуры и даже в шейдеры! Но для того чтобы это сделать стоит понять как вообще красить треугольники.

Алгоритм Брезенхема для рисования линии.

Начнем с линий. Если кто не знал алгоритм Брезенхема — это основной алгоритм рисования прямых в компьютерной графике. Он или его модификации используется буквально везде: рисование прямых, отрезков, окружностей и т.п. Кому интересно более подробное описание — читайте вики. Алгоритм Брезенхема

Имеется отрезок соединяющий точки и . Чтобы нарисовать отрезок между ними нужно закрасить все пиксели которые попадают на него. Для двух точек отрезка можно найти x-координаты пикселей в которых они лежат: нужно лишь взять целые части от координат x1 и x2. Чтобы закрасить пиксели на отрезке запускаем цикл от x1 до x2 и на каждой итерации вычисляем y — координату пикселя который попадает на прямую. Вот код:

image loader

Растеризация треугольника. Алгоритм заливки

Линии рисовать мы умеем, а вот с треугольниками будет чуть посложнее(не намного)! Задача рисования треугольника сводится к нескольким задачам рисования линий. Для начала разобьем треугольник на две части предварительно отсортировав точки в порядке возрастания x:

image loader

Заметьте — теперь у нас есть две части в которых явно выражены нижняя и верхняя границы. все что осталось — это залить все пиксели находящиеся между ними! Сделать это можно в 2 цикла: от x1 до x2 и от x3 до x2.

Несомненно этот код можно отрефакторить и не дублировать цикл:

Отсечение невидимых точек.

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

image loader

Для того, чтобы понять видима точки или нет, в рендеринге применяют механизм zbuffer-а(буфера глубины). zbuffer можно представить как двумерный массив (можно сжать в одномерный) с размерностью width * height. Для каждого пикселя на экране он хранит значение z — координаты на исходном полигоне откуда эта точка была спроецирована. Соответственно чем ближе точка к наблюдателю, тем меньше ее z — координата. В конечном итоге если проекции нескольких точек совпадают растеризировать нужно точку с минимальной z — координатой:

image loader

Теперь возникает вопрос — как находить z-координаты точек на исходном полигоне? Это можно сделать несколькими способами. Например можно пускать луч из начала координат камеры, проходящий через точку на проекционной плоскости , и находить его пересечение с полигоном. Но искать пересечения крайне затратная операция, поэтому будем использовать другой способ. Для рисования треугольника мы интерполировали координаты его проекций, теперь, помимо этого, мы будем интерполировать также и координаты исходного полигона. Для отсечения невидимых точек будем использовать в методе растеризации состояние zbuffer-а для текущего фрейма.

Мой zbuffer будет иметь вид Vector3[]он будет содержать не только z — координаты, но и интерполированные значения точек полигона(фрагменты) для каждого пикселя экрана. Это сделано в целях экономии памяти так как в дальнейшем нам все равно пригодятся эти значения для написания шейдеров! А пока что имеем следующий код для определения видимых вершин(фрагментов):

image loader

Анимация шагов растеризатора(при перезаписи глубины в zbuffer-е пиксель выделяется красным):

Для удобства я вынес весь код в отдельный модуль Rasterizer:

Теперь проверим работу рендера. Для этого я использую модель Сильваны из известной RPG «WOW»:

image loader

Не очень понятно, правда? А все потому что здесь нет ни текстур ни освещения. Но вскоре мы это исправим.

Текстуры! Нормали! Освещение! Мотор!

Почему я объединил все это в один раздел? А потому что по своей сути текстуризация и расчет нормалей абсолютно идентичны и скоро вы это поймете.

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

image loader

Заметьте, что начало текстуры (левый нижний пиксель) в текстурных координатах имеет значение , конец (правый верхний пиксель) — . Учитывайте систему координат текстуры и возможность выхода за границы картинки когда текстурная координата равна 1.

Сразу создадим класс для представления данных вершины:

Зачем нужны нормали я объясню позже, пока что просто будем знать, что у вершин они могут быть. Теперь для текстуризации полигона нам необходимо каким-то образом сопоставить значение цвета из текстуры конкретному пикселю. Помните как мы интерполировали вершины? Здесь нужно сделать то же самое! Я не буду еще раз переписывать код растеризации, а предлагаю вам самим реализовать текстурирование в вашем рендере. Результатом должно быть корректное отображение текстур на модели. Вот, что получилось у меня:

image loader

Вся информация о текстурных координатах модели находятся в файле OBJ. Для того, чтобы использовать это изучите формат: Формат OBJ.

Освещение

С текстурами все стало гораздо веселее, но по настоящему весело будет когда мы реализуем освещение для сцены. Для имитации «дешевого» освещения я буду использовать модель Фонга.

Модель Фонга

В общем случае этот метод имитирует наличие 3х составляющих освещения: фоновая(ambient), рассеянная(diffuse) и зеркальная(reflect). Сумма этих трех компонент в итоге даст имитацию физического поведения света.

image loader

Для расчета освещения по Фонгу нам будут нужны нормали к поверхностям, для этого я и добавил их в классе Vertex. Где же брать значения этих нормалей? Нет, ничего вычислять нам не нужно. Дело в том, что великодушные 3д редакторы часто сами считают их и предоставляют вместе с данными модели в контексте формата OBJ. Распарсив файл модели мы получаем значение нормалей для 3х вершин каждого полигона.

image loader

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

Фоновый свет (Ambient)

Изначально мы задаем постоянное фоновое освещение, для нетекстурированных объектов можно выбрать любой цвет, для объектов с текстурами я делю каждую из компонент RGB на некий коэффициент базового затенения (baseShading).

Рассеянный свет (Diffuse)

Когда свет падает на поверхность полигона он равномерно рассеивается. Для расчета diffuse значения на конкретном пикселе учитывается угол под которым свет падает на поверхность. Чтобы рассчитать этот угол можно применить скалярное произведение падающего луча и нормали(само собой вектора перед этим нужно нормализировать). Этот угол будет умножаться на некий коэффициент интенсивности света. Если скалярное произведение отрицательно — это значит, что угол между векторами больше 90 градусов. В этом случае мы начнем рассчитывать уже не осветление, а, наоборот, затенение. Стоит избегать этого момента, сделать это можно с помощью функции max.

Давайте применим рассеянный свет и рассеем тьму:

image loader

Зеркальный свет (Reflect)

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

image loader

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

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

image loader

Конечной точкой моего изложения будет реализация теней для рендера. Первая тупиковая идея которая зародилась у меня в черепушке — для каждой точки проверять не лежит ли между ней и светом какой-нибудь полигон. Если лежит — значит не нужно освещать пиксель. Модель Сильваны содержит 220к с лихвой полигонов. Если так для каждой точки проверять пересечение со всеми этими полигонами, то нужно сделать максимум 220000 * 1920 * 1080 * 219999 вызовов метода пересечения! За 10 минут мой компьютер смог осилить 10-у часть всех вычислений (2600 полигонов из 220000), после чего у меня случился сдвиг и я отправился на поиски нового метода.

В интернете мне попался очень простой и красивый способ, который выполняет те же вычисления в тысячи раз быстрее. Называется он Shadow mapping(построение карты теней). Вспомните как мы определяли видимые наблюдателю точки — использовали zbuffer. Shadow mapping делает тоже самое! В первом проходе наша камера будет находиться в позиции света и смотреть на объект. Таким образом мы сформируем карту глубин для источника света. Карта глубин — это знакомый нам zbuffer. Во втором проходе мы используем эту карту, чтобы определять вершины которые должны освещаться. Сейчас я нарушу правила хорошего кода и пойду читерским путем — просто передам шейдеру новый объект растеризатора и он используя его создаст нам карту глубин.

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

image loader

Многие из вас наверное заметили артефакты данного шейдера(необработанные светом черные точки). Опять же обратившись в всезнающую сеть я нашел описание этого эффекта с противным названием «shadow acne»(да простят меня люди с комплексом внешности). Суть таких «зазоров» заключается в том, что для определения тени мы используем ограниченное разрешение карты глубин. Это значит, что несколько вершин при рендеринге получают одно значение из карты глубин. Такому артефакту наиболее подвержены поверхности на которые свет падает под пологим углом. Эффект можно исправить, увеличив разрешение рендера для света, однако существует более элегантный способ. Заключается он в том, чтобы добавлять определенный сдвиг для глубины в зависимости от угла между лучом света и поверхностью. Это можно сделать при помощи скалярного произведения.

image loader

Играем с нормалями

Я подумал, стоит ли интерполировать значения нормалей, если можно посчитать среднее между 3мя нормалями полигона и использовать для каждой его точки. Оказывается, что интерполяция дает куда более естественный и гладкий материал картинки.

Двигаем свет

Реализовав простой цикл получим набор отрендеренных картинок с разными позициями света на сцене:

image loader

Производительность

Для теста использовалась следующие конфигурации:

Источник

Оцените статью
Avtoshod.ru - все самое важное о вашем авто