- Компьютерная диагностика двигателя автомобиля: что в нее входит
- Что такое компьютерная диагностика и как её проводят
- В каких областях применяют компьютерную диагностику, когда речь идет об автомобиле
- Что показывает компьютерная диагностика двигателя
- Функции компьютерной диагностики
- Компьютерная диагностика — описание
- Что выявляет компьютерная диагностика
- Что включает компьютерная диагностика автомобиля
- Напутствие
- Создаём собственный программный 3D-движок
- Основные систем координат
- Система координат
- Обозначение точек
- Взаимная перпендикулярность
- Точки и векторы
- Создание движка
- Заключение
- Часть 2: линейные преобразования
- Основы линейных преобразований
- Повороты
- Упражнение: функции поворота
- Масштабирование
- Упражнение: функции масштабирования
- Давайте что-нибудь создадим!
- Заключение
- Часть 3: пространства и отсечение
- Отсечение
- Может, пора добавить камеру?
- Управление точками
- Больше и лучше
- Заключение
- Часть 4: растеризация отрезков прямых и окружностей
- Растеризация
- Отрезки прямых
- Окружности
- Мастер растеризации
- Заключение
- Часть 5: растеризация треугольников и четырёхугольников
- Растеризация треугольников
- Работаем с квадратами
- Работаем с полигонами
- Создатель полигонов
- Заключение
- Часть 5: цвета
- Цвет для всех!
- Экспериментируем с 16,7 миллиона цветов
- Заключение
- Часть 7: динамическое освещение
- Повторение
- Класс освещения
- Свет? Камера? Мотор.
- Следуй за светом
- Заключение
Компьютерная диагностика двигателя автомобиля: что в нее входит
Эта процедура позволяет отслеживать основные характеристики работы мотора (в некоторых ситуациях даже корректирует ее). При возникновении неисправности профессионалы автосервиса смогут провести тестирование без разбора авто.
Автоматизированная система с цифровыми датчиками дает возможность за короткое время проверить силовой агрегат на проблемы и вовремя их устранить.
Узнайте стоимость компьютерной диагностики двигателя онлайн за 3 минуты
Не тратьте время впустую – воспользуйтесь поиском Uremont и получите предложения ближайших сервисов с конкретными ценами!
Что такое компьютерная диагностика и как её проводят
Когда не было возможности проверить работу своими руками, используя электронные диагностические датчики, потенциальную опасность для двигателя определяли только по определенным признакам. В этой ситуации при устранении одной проблемы оставался риск упустить другие поломки.
Электронная система управления мотора “собирает” статистические данные по работе “сердца” авто, анализируя полученные данные. Это позволяет определить узел, в котором идентифицирован сбой.
В каких областях применяют компьютерную диагностику, когда речь идет об автомобиле
Целью такой проверки является информация о:
- состоянии машины на текущий момент;
- способах повышения функциональной эффективности автосистем;
- необходимых мерах по устранению неисправностей.
На дисплей выводятся коды ошибок, которые расшифровывают специальным ридером кодов, диагностического стенда и сканера. На основании этой информации принимается решение о необходимых превентивных или корректирующих работах. Таким образом осуществляется проверка не только “движка”, но и КПП, подвески и пр.
Что показывает компьютерная диагностика двигателя
Еще раз повторим, что подобная опция позволяет оптимизировать процедуру автодиагностики и узнавать точную информацию. Сканер с корректно настроенным ПО, распознающим и анализирующим полученную информацию.
Что показывает компьютерная диагностика автомобиля? Прежде чем ответить на этот вопрос, предлагаем смотреть на сигналы, свидетельствующие о неисправности. У подвески это:
- неравномерный износ шин;
- появление гулов на крутых поворотах или при езде по неровному покрытию;
- смещение оси на виражах;
- преждевременное срабатывание АБС;
- возрастание свободного хода руля.
С “сердцем” автомобиля серьезная проверка требуется при увеличении времени разогрева, расхода топлива и признаках неустойчивой работы. А также при потере мощности, белом/черном “выхлопе”, обнаружении посторонних шумов, повышении/понижении холостых оборотах.
Функции компьютерной диагностики
Подобную проверку делают для предотвращения компьютерного сбоя и отказа сложных функциональных механизмов. Такие мероприятия включают получение и обработку сообщений об ошибках работы главных систем и узлов.
Для проведения такой работы понадобятся следующие средства контроля:
- многофункциональные стенды;
- диагностические сканеры;
- портативные считыватели/ридеры.
Перечисленные выше устройства работают через специальный разъем автомобиля. Специализированный компьютер и программное обеспечение позволяют зафиксировать нежелательные функциональные изменения в работе автосистем. Также можно удалять коды, чтобы их скорректировать.
Компьютерная диагностика — описание
Скорость системы позволяет собрать данные в пределах получаса и интерпретировать полученные данные по одному из автомобильных узлов за считаные секунды. В результате мастер без особых трудностей составит правильный план ремонта.
При проверке обязательно учитывается давление:
- барометрическое (в норме совпадает с атмосферным);
- впускного коллектора (при теплом “движке” и на холостом ходу с выключенными автоприборами должно составлять 30-33 кПа).
Также обязательно учитывается накопленная коррекция подачи топлива, которая должна стремиться к нулю.
Что выявляет компьютерная диагностика
Кроме комплексных сведений, можно протестировать отдельные узлы, системы и детали:
- бортовую электронику;
- коробку;
- ходовую (в т. ч. ее вспомогательные элементы) и пр.
Помимо очевидных поломок, такая проверка позволяет предупредить дорогой ремонт. Если на приборной панели загорелся индикатор Check Engine (или другие лампочки), нужно проверить авто в ближайшее время. Таким образом вы защитите себя от неприятных неожиданностей на дороге и сэкономите деньги, не допустив серьезной поломки.
Что входит в компьютерную диагностику двигателя авто? Этот процесс нацелен на поиск проблемных узлов, после которой понятно, какие запчасти надо заменить и степень аварийности ситуации. Например, отсутствие компрессии или износ вкладышей свидетельствуют о высокой вероятности отказа поршней. В экстренных ситуациях специалист предупредит автовладельца о необходимости срочных мер.
Что включает компьютерная диагностика автомобиля
Комплексное обследование состоит из проверки:
- отопительной и охлаждающей систем;
- силового агрегата;
- электрооборудования (проводка и целостность ее обмотки, стартеры, генераторы и прочие необходимые элементы);
- ходовой, тормозов, сцепления (в том числе АБС и Airbags).
Ранее мы выяснили, что проверяет компьютерная диагностика автомобиля. Такая услуга в любом автосервисе включает внешний осмотр, тестирование двигательной функции, детальное обследование ходовой и комплексное программное тестирование. Обязательно исследуют световое оборудование на работоспособность. Дают оценку состояния салона и кузовного покрытия. Часть обнаруженных проблем профессионал может сразу ликвидировать, утвердив это с автовладельцем (например, полируют фары и кузов, устраняют существенные загрязнения, ремонтируют мелкие царапины, меняют стекла).
Что входит в компьютерную диагностику ДВС автомобиля? Перечень обязательных работ приведен ниже:
- общий осмотр (капота и пространства под ним, наличие/состояние датчиков, хомутов, проводов);
- проверка форсунок мультиметром;
- комплексное тестирование сканером (проверяется электрооборудование);
- диагностика фильтрующей системы (степень загрязнения, дату монтажа и пр.);
- исследование свечей (для этого понадобятся наименование бренда и цвет автомобиля, провести внешний осмотр);
- проверка сканером-тестером (определяет тип и дату установки ЭБУ, на этом этапе вносят правки в ПО машины);
- диагностика степени цилиндрической компрессии.
Напутствие
Будьте внимательны к сигналам бортовой системы о возможных проблемах и не откладывайте надолго поиск их источника. Проводите регулярное компьютерное исследование авто, чтобы предотвратить отказ ключевых автомобильных систем. Доверьте эту работу техцентру, так как для качественного результата требуются специальные навыки и оборудование.
Агрегатор Uremont.com предлагает для поиска СТО воспользоваться следующими сервисами:
- онлайн-бланком заявки на проведение работ;
- оценками и отзывами пользователей о партнерских автомастерских;
- чатом с профессионалами;
- картой для поиска удобного адреса техцентра и пр.
Создаём собственный программный 3D-движок
Современные трёхмерные игровые движки, используемые в крупнейших проектах — это тонкая смесь математики и программирования. Многие программисты игр признают, что всецело понять их очень непросто. Если вам не хватает опыта (или профессионального образования, как мне), эта задача становится ещё более сложной. Я хочу познакомить вас с основами графических систем 3D-движков.
В этой части мы рассмотрим точки и векторы, а также всё интересное, что с ними связано. Если вы владеете основами алгебры (переменные и математика переменных) и информатики (основы любого объектно-ориентированного языка), то сможете разобраться в этой статье. Но учтите, некоторые из тем будут довольно сложными.
Основные систем координат
Начнём с азов. Для трёхмерной графики требуется концепция трёхмерного пространства. Наиболее часто из всех видов пространств используется декартово пространство, которое позволяет нам применять декартовы координаты (стандартная запись и двухмерные графики, которые изучают в большинстве школ).
Проклятье, отравляющее жизнь многим школьникам
Трёхмерное декартово пространство даёт нам оси x, y и z (описывающие положение по горизонтали, вертикали и в глубину). Координаты любой точки в этом пространстве обозначаются как несколько чисел (в нашем случае три числа, потому что у нас три оси). На двухмерной плоскости запись обозначается как , а в трёхмерном пространстве — как
. Эта запись (кортеж) показывает положение точки относительно исходной точки пространства (которая обычно обозначается как
.
Подсказка: кортеж — это упорядоченный список (или последовательность) элементов в информатике или математике. То есть запись будет кортежем из четырёх элементов, показывающим последовательность символов, составляющих моё имя.
В этом пространстве мы будем определять точку как кортеж из трёх элементов. Это можно обозначить так:
Кроме задания точки нам нужно определить её части.
Каждый из элементов кортежа является скалярным числом, определяющим положение вдоль базисного вектора. Каждый базисный вектор должен иметь единичную длину (его длина равна 1), то есть такие кортежи как и
не могут быть базисными векторами, потому что они слишком длинные.
Мы определим три базисных вектора в нашем пространстве:
Источник: http://www.thefullwiki.org/Arithmetics/Cartesian_Coordinate.
Система координат
Теперь поговорим о математическом определении нашей системы координат, о том, как она влияет на графическую систему и о вычислениях, которые мы можем произвести.
Обозначение точек
Точку начала координат системы координат можно обозначить точкой , которая описывается кортежем из трёх элементов (0,0,0). Это значит, что математическое представление системы координат можно изобразить так:
Этой записью мы можем сказать, что представляют собой положение точки относительно начала координат. Такое определение означает, что любую точку
,
можно представить как:
С этого момента мы будем обозначать скалярные значения строчными буквами, а векторы — прописными, то есть ,
и
— это скаляры, а
,
и
— векторы. (На самом деле это базисные векторы, определение которым мы дали выше.)
Это значит, что точка, записываемая кортежем (2,3,4), может быть представлена так:
Итак, мы взяли абстрактное понятие «точки в трёхмерном пространстве» и определили его как сумму четырёх объектов. Такое определение будет очень важным, когда дело дойдёт до реализации понятия в коде.
Взаимная перпендикулярность
Система координат, которую мы будем использовать, обладает очень ценным свойством: взаимной перпендикулярностью. Это значит, что в пересечении каждой из осей на своей соответствующей плоскости угол между ними равен 90 градусам.
Нашу систему координат можно также назвать «правой»:
Источник: http://viz.aset.psu.edu/gho/sem_notes/3d_fundamentals/html/3d_coordinates.html.
На языке математики это значит, что:
где обозначает оператор векторного произведения.
Векторное произведение можно определить следующим уравнением (при условии, что у нас есть два кортежа из трёх элементов):
Эти выражения могут показаться скучными, но позже они позволят нам проще выполнять множество различных вычислений и преобразований. К счастью, при создании игрового движка нам необязательно запоминать все эти уравнения — можно начать с этих выражений, а затем надстраивать поверх них менее сложные системы. По крайней мере, пока вы не захотите изменить в движке нечто фундаментальное!
Точки и векторы
Определившись с основами системы координат, мы можем поговорить о точках и векторах, и, что более важно — о том, как они взаимодействуют друг с другом. По-первых, стоит заметить, что точки и векторы — это совершенно разные объекты: точка — это физическое место в пространстве, вектор — пространство между двумя точками.
Чтобы не перепутать эти два типа объектов, я буду записывать точки курсивными прописными буквами, например, , а векторы — полужирными прописными, например,
.
При работе с точками и векторами мы будем использовать две основные аксиомы. Вот они:
- Аксиома 1: разность между двумя точками — это вектор, то есть
- Аксиома 2: сумма точки и вектора — это точка, то есть
Подсказка:аксиома — это логическое утверждение, считаемое достаточно очевидным для принятия без доказательств.
Создание движка
Благодаря этим двум аксиомам у нас есть достаточно информации для создания классов-«кирпичиков», которые являются сердцем любого трёхмерного игрового движка: класса Point и класса Vector . Если бы мы собирались создавать свой движок на основе этой информации, то нам бы нужно было сделать и другие важные шаги при создании этих классов (в основном связанных с оптимизацией и работой с существующими API), но мы опустим это ради упрощения.
Все примеры классов будут написаны псевдокодом, чтобы вы могли реализовать их на своём любимом языке. Вот наброски наших двух классов:
В качестве упражнения попробуйте заполнить каждую из функций этих классов работающим кодом (на основании того, что мы разобрали выше). Закончив с этим, протестируйте работу, выполнив эту простую программу:
Заключение
Мы добрались до конца первой части! Кажется, что тут использована куча математики просто для написания двух классов, и это на самом деле так. В большинстве случаев вам никогда не придётся работать с игрой на таком уровне, но знание подробностей внутренней работы игрового движка всё равно будет полезным (хотя бы для собственного удовольствия).
Часть 2: линейные преобразования
Теперь мы поговорим о линейных преобразованиях, которые позволят нам изменять такие свойства векторов, как поворот и масштаб. Мы узнаем, как применить их в уже созданных нами классах.
Для обсуждения линейных преобразований нам нужно внести небольшое изменение в класс Point: вместо вывода данных в консоль воспользуйтесь любым удобным вам графическим API, чтобы функция отрисовывала текущую точку на экране.
Основы линейных преобразований
Просто предупреждение: уравнения линейных преобразований всегда выглядят намного сложнее, чем есть на самом деле. Мы применим тригонометрию, но вам на самом деле не обязательно знать как выполняются тригонометрические операции: я объясню, что нужно будет передавать каждой функции и что мы будем от неё получать, а для всех промежуточных действий можно использовать любой калькулятор или математическую библиотеку.
Подсказка: если вы хотите глубже разобраться во внутренней работе этих уравнений, то стоит посмотреть это видео и прочитать этот PDF.
Все линейные преобразования имеют следующую форму:
Из этого понятно, что у нас есть функция преобразования , в качестве входных данных используется вектор
, а на выходе мы получим вектор
.
Каждую из этих частей — два вектора и функцию — можно представить в виде матрицы: вектор — как матрицу 1×3, вектор
— как ещё одну матрицу 1×3, а линейное преобразование
— как матрицу 3×3 (матрицу преобразований).
Это значит, что развернув уравнение, мы получим следующее:
Если вы проходили тригонометрию или линейную алгебру, то, возможно, уже припоминаете кошмар математики матриц. К счастью, есть более простой способ записи этого выражения, позволяющий избавиться от большинства проблем. Он выглядит вот так:
Однако эти уравнения могут меняться при наличии второго источника входных данных, как в случае с поворотами, когда должны задаваться вектор и количество его вращения. Давайте посмотрим, как работают повороты.
Повороты
Поворот, по самому определению — это круговое движение объекта вокруг точки поворота. Точка поворота в нашем пространстве может принадлежать плоскости XY, плоскости XZ или плоскости YZ (где каждая плоскость составлена из двух базисных векторов, которые мы обсуждали в первой части).
Три точки поворота означают, что у нас есть три отдельных матрицы вращения:
Матрица поворота по XY:
Матрица поворота по XZ:
Матрица поворота по YZ:
То есть для поворота точки вокруг плоскости XY на 90 градусов (
радиан — в большинстве математических библиотек есть функция преобразования градусов в радианы), нужно выполнить следующие действия:
То есть если начальная точка имела координаты
, то выходная точка
будет иметь координаты
.
Упражнение: функции поворота
В качестве упражнения попробуйте создать три новые функции для класса Vector . Одна должна поворачивать вектор вокруг плоскости XY, другая — вокруг YZ, а третья — вокруг XZ. На входе функции должны получать нужное число градусов поворота, а на выходе возвращать вектор.
В целом функции должны работать следующим образом:
- Создание выходного вектора.
- Преобразование входа в градусах в радианы.
- Решение каждого из элементов кортежа выходного вектора с помощью приведённых выше уравнений.
- Возврат выходного вектора.
Масштабирование
Масштабирование — это преобразование, увеличивающее или уменьшающее объект в соответствии с заданным масштабом.
Это преобразование выполнить довольно просто (по крайней мере, по сравнению с поворотами). Преобразование масштабирования требует двух типов входных данных: входного вектора и кортежа масштабирования из трёх элементов, который определяет масштаб входного вектора по каждой из осей пространства.
Например, в кортеже масштабирования величина
представляет собой масштаб по оси X,
— по оси Y, а
— по оси Z.
Матрица масштабного преобразования имеет следующий вид (где ,
и
— это элементы кортежа масштабирования):
Чтобы сделать входной вектор A вдвое больше по оси X (то есть использовать кортеж
), вычисления должны иметь следующий вид:
То есть при входном векторе выходной вектор
будет равен
.
Упражнение: функции масштабирования
В качестве ещё одного упражнения добавьте новую функцию в класс Vector. Эта новая функция должна получать кортеж масштабирования и возвращать выходной вектор.
В целом функция должна работать следующим образом:
- Создание выходного вектора.
- Решение каждого элемента кортежа выходного вектора с помощью приведённого выше уравнения (которое можно упростить до y0 = x0 * s0; y1 = x1*s1; y2 = x2*s2 ).
- Возврат выходного вектора.
Давайте что-нибудь создадим!
Теперь, когда у нас есть в распоряжении линейные преобразования, давайте создадим небольшую программу, чтобы продемонстрировать новые возможности. Мы создадим программу, отрисовывающую на экране группу точек и позволяющую изменять их как целое, выполняя над ними линейные преобразования.
Прежде чем начать, нам нужно добавить ещё одну функцию в класс Point . Мы назовём её setPointToPoint() , она будет просто задавать положение текущей точки в точке, которая ей передаётся. На входе она будет получать точку и ничего не возвращать.
Вот краткие характеристики программы:
- Программа будет хранить в массиве 100 точек.
- При нажатии клавиши D программа будет очищать текущий экран и перерисовывать точки.
- При нажатии клавиши A программа будет масштабировать положения всех точек на 0,5.
- При нажатии клавиши S программа будет масштабировать положения всех точек на 2,0.
- При нажатии клавиши R будет поворачивать положение всех точек на 15 градусов на плоскости XY.
- При нажатии клавиши Escape программа закрывается (если вы не пишете её на JavaScript или другом веб-ориентированном языке).
Имеющиеся у нас классы:
Давайте посмотрим, как может выглядеть код с учётом приведённых требований:
Итак, у нас получилась короткая хорошая программа, демонстрирующая все наши новые возможности!
Заключение
Хоть мы и не рассмотрели все возможные линейные трансформации, наш микродвижок начинает обретать свою форму.
Как обычно, для упрощения я убрал из движка некоторые вещи (а именно перемещение и отражения). Если вы хотите больше узнать об этих двух типах линейных преобразований, то можете почитать в статье Википедии и по ссылкам в статье.
В следующей части мы рассмотрим различные пространства обзора и отсечение объектов, находящихся за пределами области видимости.
Часть 3: пространства и отсечение
Видно, что пока использование двух созданных нами классов самих по себе — довольно запутанный процесс, к тому же отрисовка каждой возможной точки может довольно быстро истощить память системы. Для решения этих проблем мы добавим в игровой движок новый класс: камеру.
Рендеринг будет происходить только в пределах камеры, она отсекает все объекты до размеров экрана, а также управляет всеми нашими точками.
Но прежде чем мы приступим ко всему этому, надо для начала поговорить об отсечении.
Отсечение
По своему определению отсечение — это выборка объектов из большей группы объектов. В нашем игровом движке меньшей группой будут точки, которые нужно отрисовать на экране. Большей группой объектов будет множество всех существующих точек.
Благодаря отсечению движок значительно снизит потребление памяти системы. Он будет отрисовывать только то, что игрок может увидеть, а не весь мир точек. В нашем движке мы реализуем это заданием параметров пространства обзора.
Пространство обзора будет задаваться по всем трём нашим традиционным осям: x, y и z. Её границы по x состоят из всего между левой и правой границами окна, границы по y — из всего между верхней и нижней границами окна, а границы по z находятся в пределах от 0 (куда установлена камера) до расстояния видимости игрока (в нашем демо мы будем использовать произвольно выбранное значение 100 ).
Перед отрисовкой точки класс камеры будет проверять, находится ли точка в пространстве обзора. Если находится, то точка отрисовывается, в противном случае — не отрисовывается.
Может, пора добавить камеру?
Поняв основы отсечения, мы можем создать класс камеры:
Также мы возложим на камеру весь процесс рендеринга в движке. Часто в движках рендереры отделены от систем камер. Обычно это делается для удобства инкапсуляции систем, потому что в некоторых движках при их совместном хранении возникает путаница. Однако для нашего туториала будет проще обращаться с ними как с единой системой.
Для начала нам потребуется функция, которую можно будет вызывать извне из класса для отрисовки сцены. Эта функция будет циклически перебирать все существующие точки, сравнивать их с параметрами отсечения камеры и отрисовывать их при соблюдении условий.
Источник: http://en.wikipedia.org/wiki/File:ViewFrustum.svg
Подсказка: если вы хотите отделить систему камер от рендерера, то можно просто создать класс Renderer , отсечь системой камер точки, сохранить в массиве те из них, которые нужно отрисовывать, а затем отправить массив в функцию draw() рендерера.
Управление точками
Последней частью класса камеры будет система управления точками. В зависимости от используемого языка программирования это может быть просто массив всех объектов для отрисовки (позже мы будем обрабатывать не только точки), или же может потребоваться использование родительского класса объектов по умолчанию. Если вам очень не повезло с выбором, то придётся реализовать собственный родительский класс объектов и сделать так, чтобы все отрисовываемые классы (пока это только точки) наследовали от этого класса.
После добавления системы управления в класс наша камера будет выглядеть примерно так:
Внеся все эти дополнения, давайте немного улучшим программу, написанную в прошлой части.
Больше и лучше
Мы собираемся создать простую программу отрисовки точек на основе примера программы, созданной в прошлой части.
В этой итерации программы мы добавим использование нового класса камеры. При нажатии клавиши D программа будет перерисовывать экран без отсечения, показывая количество отрендеренных объектов в верхнем правом углу экрана. При нажатии клавиши C программа будет перерисовывать экран с отсечением, также показывая количество отрендеренных объектов.
Давайте взглянем на код:
Теперь вы своими глазами можете увидеть всю мощь отсечения! Заметьте, что в коде примера, некоторые вещи реализуются немного иначе, чтобы сделать демо более веб-совместимым.
Заключение
Создав систему камер и рендеринга, технически можно сказать, что у нас есть готовый трёхмерный игровой движок! Пока он не слишком впечатляет, но всему своё время.
В следующей части мы узнаем, как добавить в движок геометрические формы (а именно отрезки прямых и окружности), а также поговорим об алгоритмах, которые можно использовать для приведения их уравнений к экранным пикселям.
Часть 4: растеризация отрезков прямых и окружностей
Растеризация
Растеризация — это процесс преобразования формы, описанной в векторном графическом формате (или в нашем случае математически) в растровое изображение (в котором форма вписывается в пиксельную структуру).
Поскольку математика не всегда так точна, как нам нужно для компьютерной графики, нам нужно использовать алгоритмы для адаптации описанной ею форм в наш целочисленнй экран. Например, в математике точка может находиться в координате , но при рендеринге необходимо сместить её в
, чтобы она вписывалась в пиксельную структуру экрана.
Для каждого типа форм будет собственный алгоритм растеризации. Давайте начнём с наиболее простых для растеризации форм: отрезка прямой.
Отрезки прямых
Источник: http://en.wikipedia.org/wiki/File:Bresenham.svg
Отрезки прямых — это одни из простейших изображаемых форм, поэтому часто это одно из первых понятий, изучаемых на геометрии. Они описываются двумя отдельными точками (начальной и конечной) и соединяющей их прямой. Наиболее часто используемый алгоритм растеризации отрезка прямой называется алгоритмом Брезенхэма.
Поэтапно алгоритм Брезенхэма выглядит так:
- Получение на входе начальной и конечной точек отрезка прямой.
- Определение направления отрезка прямой вычислением его свойств
и
(
,
).
- Определение свойств sx , sy и обнаружения ошибки (математическое определение приведено ниже).
- Округление каждой точки в отрезке до пикселя выше/ниже.
Перед реализацией алгоритма Брезенхэма давайте создадим базовый класс отрезка, который можно будет использовать в движке:
Если нужно выполнить преобразование с новым классом LineSegment , то для этого достаточно применить соответствующее преобразование к начальной и конечной точкам LineSegment , а затем передать их обратно в класс. Все точки между нии будут обработаны при отрисовке самого LineSegment , потому что для поиска всех последующих точек алгоритму Брезенхэма требуются только начальная и конечная точки.
Чтобы встроить класс LineSegment в уже существующий движок, нам нужно добавить в класс функцию draw() , поэтому я отказался от использования функции returnPointsInSegment . Эта функция будет возвращать массив всех точек, находящихся в отрезке прямой, что позволит нам удобно отрисовывать и отсекать отрезок.
Функция returnPointsInSegment() будет выглядеть примерно так (в JavaScript):
Простейший способ добавить рендеринг отрезков прямых в класс камеры — добавление простой структуры if , например, вот такой:
И это всё, что понадобится для работы нашего первого класса формы! Если вы хотите подробнее узнать технические аспекты алгоритма Брезенхэма (в особенности об ошибках), то можно прочитать о них в статье в Википедии.
Окружности
Источник: http://en.wikipedia.org/wiki/File:Bresenham_circle.svg
Растеризация окружности немного сложнее, чем растеризация отрезка прямой. Для большей части работы мы будем использовать алгоритм центральной точки окружности, который является развитием алгоритма Брезенхэма. То есть он состоит из похожих этапов, с некоторыми отличиями.
Новый алгоритм будет работать так:
- Получение центральной точки и радиуса окружности.
- Принудительное задание точек в каждом основном направлении
- Циклический обход каждого из квадрантов, отрисовка их дуг
Класс окружности очень похож на класс отрезка прямой и будет выглядеть примерно так:
Функция returnPointsInCircle() будет вести себя так же, как функция класса LineSegment , возвращая массив точек, чтобы камера могла отрендерить и отсечь их. Это позволяет движку обрабатывать множество разных форм, в каждую из которых нужно вносить только незначительные изменения.
Вот как будет выглядеть функция returnPointsInCircle() (в JavaScript):
Теперь мы просто добавим ещё одну конструкцию if в основной цикл отрисовки, и эти окружности будут полностью интегрированы в код!
Вот как может выглядеть обновлённый цикл отрисовки:
Теперь, когда у нас есть два новых класса, давайте сделаем что-нибудь!
Мастер растеризации
На этот раз наша программа будет простой. Когда пользователь нажимает кнопку мыши, мы будем отрисовывать окружность с центром в точке нажатия и со случайным радиусом.
Давайте посмотрим на код:
Если всё получится успешно, то вы сможете отрисовывать с помощью движка отличные окружности.
Заключение
Добавив к движку базовые возможности растеризации, мы наконец начинаем отрисовку на экране полезных объектов! Пока не было ничего сложного, но если хотите, можете попробовать рисовать людей из отрезков и окружностей, или что-то в таком духе.
В следующей части мы ещё раз взглянем на растеризацию. Только на этот раз мы добавим в движок ещё два класса: треугольники и четырёхугольники.
Часть 5: растеризация треугольников и четырёхугольников
Для создания классов Triangle и Quad мы будем активно использовать класс LineSegment .
Растеризация треугольников
Реализация класса Triangle в движке довольно проста, особенно благодаря использованию класса LineSegment , в которой и будет происходить вся растеризация. Этот класс позволит назначить три точки и отрисовать между ними отрезки прямых, чтобы создать замкнутый треугольник.
Набросок класса будет выглядеть так:
Ради стандартизации мы предположим, что три точки объявляются в треугольнике по часовой стрелке.
Тогда с помощью класса LineSegment можно написать следующую функцию returnPointsInTriangle() :
Неплохо, правда? Мы уже проделали большую работу в классе LineSegment , поэтому нам просто последовательно соединить отрезки вместе для создания более сложных форм. Это позволяет нам с лёгкостью создавать на экране гораздо более сложные многоугольники (полигоны) простым добавлением новых LineSegment (и хранением большего количества точек в самом классе).
Теперь давайте посмотрим, как добавить в эту систему ещё точек, создав класс квадрата.
Работаем с квадратами
Для реализации класса управления четырёхугольниками нужно всего лишь добавить несколько дополнений в класс Triangle . С другим множеством точек класс четырёхугольника будет выглядеть так:
Теперь нам нужно просто добавить ещё один отрезок прямой в функцию returnPointsInQuad , вот так:
Хотя такой способ создания классов довольно прост, есть гораздо более лёгкий способ инкапсуляции всех полигонов в один класс. С помощью магии циклов и массивов мы можем реализовать класс полигонов, который сможет вмещать в себя формы почти любой сложности!
Работаем с полигонами
Для создания постоянно расширяющегося класса полигона нам нужны два серьёзных шага. Первый — поместить все точки в массив, который даст нам набросок класса, похожего на такой:
Второй — использование цикла для обхода всего неопределённого количества отрезков прямых в функции returnPointsInPolygon() , которая может выглядеть примерно так:
Добавив в движок этот класс, мы можем одной строкой кода создавать что угодно — от треугольника до 39-стороннего чудовища.
Создатель полигонов
Чтобы поэкспериментировать с новым классом полигона, давайте создадим программу, демонстрирующую все его возможности. Наша программа позволит пользователю добавлять или удалять стороны отображаемого полигона с помощью клавиш. Разумеется, нужно сделать ограничение на количество сторон полигона, потому что при меньше чем трёх сторонах он перестаёт быть полигоном. Нас не очень волнует верхний предел сторон полигона, потому что он будет хорошо масштабироваться. Однако мы ограничим количество сторон десятью, потому что будем задавать новые точки в коде.
Спецификации программы можно разбить на следующие части:
- Первоначальная отрисовка полигона на экране.
- При нажатии клавиши A снижать количество сторон полигона на 1.
- При нажатии клавиши S увеличивать количество сторон полигона на 1.
- Количество сторон полигона не должно быть меньше 3.
- Количество сторон полигона не должно быть больше 10.
Давайте посмотрим, как должен выглядеть наш код:
Наша маленькая программа теперь позволит вам менять полигон на экране! Если вы хотите сделать программу немного мощнее, то можете добавить в часть с изменением полигона какой-нибудь алгоритм для упрощения масштабирования. Не знаю, существует ли он, но если да, то вы с лёгкостью можете получить бесконечно масштабируемый полигон!
Заключение
Теперь в нашем движке довольно много операций растеризации, что позволяет нам создать почти любую необходимую форму (однако некоторые из них потребуют комбинирования). В следующей части мы отойдём от рисования форм и поговорим о других свойствах. Если вам интересно добавить на экран немного цвета, то читайте следующую часть!
Часть 5: цвета
Наш теоретический движок уже содержит почти всё необходимое, а именно:
- Классы Point и Vector (строительные кирпичики движка).
- Функции преобразований точек.
- Класс Camera (задаёт область видимости и отсекает точки за пределами экрана).
- Три класса для растеризации (отрезков прямых, окружностей и полигонов).
Теперь давайте добавим цвета!
Цвет для всех!
Наш движок будет обрабатывать цвета, храня их значения в классе Point . Это позволит каждой точке иметь собственный цвет, что намного упростит расчёты освещения и затенения (по крайней мере, для человека — иногда такой код движка менее эффективен). При вычислении освещения и затенения сцены мы можем создать функцию со списком точек и обработать все их с учётом расстояния до источника света, чтобы соответствующим образом изменить их цвет.
Один из самых стандартных способов хранения цвета в программировании — использование красного, зелёного и синего значений (обычно это называется аддитивным смешением цветов). Сохраняя значение от 0 до 255 каждого из компонентов цвета, можно создать большую палитру цветов. (Таким образом определяют цвет большинство API, поэтому для совместимости логично использовать этот способ).
В зависимости от используемого графического API эти значения можно передавать или в десятеричном ( 255,0,0 ), или в шестнадцатеричном виде ( 0xFF0000 или #FF0000 ). Мы будем использовать десятеричный формат, потому что с ним гораздо проще работать. Кроме того, если ваш графический API использует шестнадцатеричные значения, то в нём скорее всего есть функция для преобразования десятеричных значений в шестнадцатеричные, то есть это не будет проблемой.
Чтобы начать реализацию цветовой модели, мы добавим три новых переменных в класс Point: red , blue и green . Пока не происходит ничего непонятного, но вот как должен теперь выглядеть набросок нашего класса Point :
Вот и всё, что нам нужно для хранения цвета точки. Теперь нам просто нужно изменить функцию отрисовки камеры, чтобы она использовала указанный цвет.
Вид функции очень сильно зависит от используемого графического API, но во всех интерфейсах обычно есть похожая функция:
Если в вашем графическом API используются шестнадцатеричные, а не десятеричные значения цвета, то функция будет выглядеть примерно так:
В этой строке используется функция toHex() (повторюсь, в разных API названия функций будут разными), преобразующая значение RGB в шестнадцатеричное значение, чтобы не пришлось этого делать вручную.
Внеся эти изменения, вы сможете получить в сцене цветные точки. На следующем этапе мы дополним классы растеризации, чтобы можно было раскрашивать формы целиком.
Чтобы добавить в классы такую возможность, мы просто должны добавить к функциям конструкторов управление цветом. Это может выглядеть так:
Теперь нам просто нужно изменить функцию возвращаемых им точек, чтобы каждая точка в массиве имела указанный цвет. Новая функция будет выглядеть так:
Теперь каждая точка на отрезке прямой имеет одинаковый цвет, переданный в отрезок прямой. Можно использовать этот способ для задания цветов и других классов растеризации, и тогда ваша сцена будет раскрашена разными цветами!
Давайте используем наши новые возможности, написав программу.
Экспериментируем с 16,7 миллиона цветов
С помощью аддитивного смешения цветов мы с лёгкостью можем создать больше 16,7 миллиона цветов, используя простую запись ( r,g,b ). Мы создадим программу, которая пользуется всем этим огромным количеством цветов.
Мы позволим пользователю с помощью нажатий клавиш отдельно управлять красным, зелёным и синим компонентами цвета и он сможет выбрать любой понравившийся цвет.
Программа будет иметь следующие спецификации:
- Отрисовка объекта на экране.
- При нажатии клавиши A значение красного компонента снижается, при нажатии Q — увеличивается.
- При нажатии клавиши S значение зелёного компонента снижается, при нажатии W — увеличивается.
- При нажатии клавиши D значение синего компонента снижается, при нажатии E — увеличивается.
- Перерисовка объекта после обновления цвета.
- Необходимо ограничивать значения компонентов и не давать им уходить за пределы от 0 до 255.
С учётом всего этого давайте посмотрим на то, как может выглядеть набросок нашей программы:
Теперь мы можем поэкспериментировать с объектом и придать ему любой цвет!
Заключение
Мы добавили в движок цвет и теперь у нас есть всё необходимое для работы с освещением. В следующей части мы рассмотрим процесс создания источником освещения и напишем функции, позволяющие этим источникам влиять на цвета точек.
Часть 7: динамическое освещение
В этой части мы рассмотрим только самые основы динамического освещения, так что не слишком пугайтесь (вся эта тема очень обширна и о ней пишут целые книги).
Если конкретнее, то мы будем создавать одноточечную одноцветную систему динамического освещения с постоянным радиусом. Но прежде чем начать, давайте рассмотрим некоторые из ранее созданных классов, которые нам пригодятся.
Повторение
Наше динамическое освещение будет обрабатываться для каждой точки в процессе их вывода на экран. Это значит, что мы будем активно использовать два наших предыдущих класса: класс Point и класс Camera . Вот как они выглядят:
Давайте создадим на основе этой информации простой класс освещения.
Класс освещения
Пример динамического освещения. Источник: http://redeyeware.zxq.net
Для работы класс освещения потребуется некоторая информация, а именно положение, цвет, тип и интенсивность (или радиус освещения).
Как я говорил ранее, освещение будет рассчитываться для каждой точки перед её отрисовкой. Преимущества такого подхода в том, что это проще для структуры движка и переносит большую часть нагрузки программы на центральный процессор. Если вы будете вычислять освещение предварительно, то нагрузка переместится на жёсткий диск компьютера и в зависимости от конструкции движка это будет реализовать легче или сложнее.
С учётом всего этого класс будет выглядеть примерно так:
Пока мы для простоты оставим все эти значения жёстко заданными, но если вы захотите расширить возможности классов освещения, то легко сможете изменять эти значения через другие функции, конструктор и т.д.
Однако все важные вычисления для динамического освещения будут выполняться в классе камеры, поэтому давайте рассмотрим его.
Свет? Камера? Мотор.
Ещё один пример динамического освещения. Источник: http://blog.illuminatelabs.com/2010/04/hdr-and-baked-lighting.html
Теперь мы добавим в класс камеры новую переменную, которую используем для хранения источника света. Пока эта переменная будет содержать только один экземпляр источника, но её можно легко расширить, чтобы можно было хранить несколько точечных источников.
Непосредственно перед отрисовкой точки мы будем проверять, находится ли она в радиусе источника света. Если находится, то нам нужно найти расстояние между точкой и положением источника, а затем изменить цвет точки в соответствии с расстоянием.
С учётом всего этого мы можем добавить код, похожий на код из функции камеры drawScene() :
Как вы видите, наш способ изменения цвета точки пока не слишком сложен (однако существуют и многие другие, которые можно при желании использовать). Мы меняем цвет точки на процент, зависящий от расстояния до центра источника освещения. Наш способ освещения совершенно не учитывает затенения, поэтому далёкие от источника света точки не становятся темнее, а объекты не перекрывают свет от других объектов, которые могут находиться за ними.
Следуй за светом
На этот раз в программе мы будем использовать несколько постоянных форм на экране. Вы можете выбрать любые формы, но в нашем примере я использую несколько простых точек. Когда пользователь нажимает мышью на экране, мы создаём в этой точке источник света. При следующем нажатии мы перемещаем точку в новое положение, и так далее. Это позволит нам понаблюдать за динамическим освещением в действии.
Вот как может выглядеть программа:
Теперь вы сможете оценить динамическое освещение в действии и увидеть, какую глубину оно добавляет игровому движку.
Заключение
Хотя наше динамическое освещение и простое, его можно при желании запросто расширить. Некоторые довольно простые, но интересные дополнения:
- изменяемый радиус освещения
- изменяемый цвет освещения (вместо однообразного изменения цвета можно изменять его на часть заданного цвета)
- блокировка света сплошными объектами
- обработка нескольких источников света
- добавление тени всем точкам за пределами радиуса источника света
- эксперименты с другими типами источников (направленный, конический и т.д.)