Без доступа к графическому процессору нам придется действовать по старинке.

Впервые я научился программировать на 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. Я поделился этим здесь в ответ на несколько сообщений на форуме, в которых просят о чем-то похожем.

Вы можете найти полный код здесь: