Без доступа к графическому процессору нам придется действовать по старинке.
Впервые я научился программировать на Atari ST в конце 80-х - начале 90-х годов. Тогда у нас не было таких фреймворков, как OpenGL или Metal; не было «почти прямого доступа к графическому процессору». Итак, как и наши предки, мы создавали 3D-движки сложным путем, с нуля, используя математику.
Хотя Flutter использует OpenGL для рендеринга своих виджетов, он не предоставляет нам API для доступа к базовому оборудованию. Если мы не можем использовать графический процессор, нам придется вместо этого производить вычисления на центральном процессоре.
Средство визуализации ЦП не будет быстрым, но его легко понять, легко построить и все же можно использовать для некоторых интересных эффектов.
Давайте начнем.
Для начала нам понадобится 3D-модель.
Хотя существует множество форматов файлов для 3D-данных, самым простым, вероятно, является Формат объекта Wavefront. Это содержит; список точек, список лиц и несколько ссылок на такие вещи, как цвет и текстура, все в виде удобочитаемого текста.
Сначала мы включим файл объекта (.obj) и материала (.mtl) в наш pubspec.yaml, а затем загрузим их в виде строк, используя Global rootBundle Flutter.
Получив строки, мы разберем их на объекты. Результатом является список точек в трехмерном пространстве и список треугольников, которые ссылаются на эти точки.
Теперь нам понадобится математика
У нас есть наша модель; теперь нам нужно вращать, масштабировать и трансформировать его. В Intenet есть множество руководств по 3D-графике, я не буду здесь все описывать, но основы таковы:
Для каждой точки в нашей модели мы вращаем, перемещаем и масштабируем ее вокруг ее исходной точки. Затем мы сортируем лица по их расстоянию от камеры и рисуем их, начиная с самых удаленных.
Все это мы делаем в методе paint()
виджета с отслеживанием состояния, который расширяет класс CustomPainter()
.
Критический вызов здесь - _calcVertex()
; это тот, кто делает основную часть математики.
Мы используем матрицу 4x4, чтобы вращать, перемещать и масштабировать нашу вершину за один проход. Помимо нескольких расчетов освещения, вся векторная математика в этом проекте использует библиотеку векторной математики Dart.
Мы готовы нарисовать нашу модель
Наконец-то мы готовы. Для каждого лица мы рассчитываем освещение, получаем значение цвета на основе его яркости и рисуем лицо с помощью команды Path()
Дарта.
Добавление пользовательских элементов управления
Наша последняя задача - позволить пользователю повернуть модель. Flutter упрощает это с помощью dragUpdateHandler
.
Последние мысли
Эта статья не является серьезной попыткой создания 3D-движка, а скорее упражнением, чтобы узнать больше о Flutter и Dart. Я поделился этим здесь в ответ на несколько сообщений на форуме, в которых просят о чем-то похожем.
Вы можете найти полный код здесь: