Настольный просмотрщик каркасных 3D-моделей с поддержкой STL и OBJ, написанный на современном C++ с юнит-тестами, drag&drop, записью GIF, авто-поворотом и сохранением пользовательских настроек.
- Ключевые возможности
- Пользовательский опыт
- Производительность и масштабируемость
- Как запустить
- Структура проекта
- Архитектура
- Примеры кода
- Инструменты и автоматизация
- Примеры данных
- Документация
- Мультимедиа
- Идеи для развития
- Лицензия
| Возможность | Что даёт |
|---|---|
| Двойной загрузчик | Поддержка OBJ (включая квады, текстурные и нормалевые индексы) и ASCII/бинарных STL с дедупликацией вершин. |
| Точные трансформации | Перемещение, вращение и масштабирование со спинбоксами, автоцентрированием и стеком undo/redo. |
| Управление рендерингом | Переключение между параллельной и перспективной проекцией, настройка стиля рёбер, вершин, цветов и толщины линий. |
| Экспорт изображений и GIF | Снимки экрана в PNG/BMP/JPEG и запись 5-секундных 640x480 GIF-анимаций (при наличии giflib). |
| Сохранение настроек | QSettings запоминает геометрию окна, палитру, параметры линий и последний выбранный пример. |
| Телеметрия | В статус-баре отображаются количество вершин/рёбер, число отрисованных сегментов и время кадра. |
- Перетащите
.objили.stlпрямо на сцену или выберите модель из встроенного набора. - Все ключевые действия (загрузка, сохранение, запись GIF, авто-ротация, автоподгонка) доступны с тулбара.
- Авто-поворот с регулируемой скоростью идеально подходит для презентаций и записи GIF.
- Боковая панель сгруппирована по сценариям: проекция, стиль, трансформации – минимальный порог входа.
- Undo/redo фиксируют целые сессии взаимодействия, поэтому можно смело экспериментировать.
- Статус-бар отображает предупреждения (например, когда в файле нет граней) и подтверждает действия.
- Граф сцены кеширует список рёбер и может отдавать пониженное количество сегментов для предпросмотра.
- STL-импорт использует 64-битный хеш для дедупликации вершин и спокойно работает с миллионом треугольников.
- CLI
meshgenгенерирует сетки от 100k до 1M вершин для стресс-тестов (make gen_1m). - Статистика кадра в статусе показывает время отрисовки в миллисекундах — узкие места сразу видны.
- CMake 3.16+
- Компилятор с поддержкой C++20 (проверено на Clang и GCC)
- Qt 5 или Qt 6 Widgets (dev-пакеты)
- giflib (опционально, для записи GIF)
cd src
make run # конфигурация CMake, сборка и запуск GUI
make build CONFIG=Debug # только сборка (по умолчанию Release)
make install PREFIX=$HOME/.local
make uninstall # удалить установленный бинарник и ресурсы
make clean # удалить каталог src/buildcd src
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
./build/3dviewercd src
make tests # или: ctest --test-dir build --output-on-failurecd src
make gcov_report
# HTML-отчёт появится в src/build/coverage/html/index.htmlsrc/
app/ # Точка входа, запуск QApplication
controller/ # Контроллер-фасад и стек команд (undo/redo)
model/ # Меш, загрузчики, трансформации, стратегии проекций
view/ # Qt-виджеты: канвас, главное окно, рекордер GIF
tools/ # meshgen — генератор больших OBJ
tests/ # Наборы GoogleTest для загрузчиков, меша и трансформаций
models/ # Встроенные примеры моделей
dvi/ # Документация (опционально)
pic/ # Папка для GIF-анимаций и скриншотов, используемых в README
Makefile # Обёртка над CMake со вспомогательными целями
CMakeLists.txt # Основной сценарий сборки
- MVC:
view/содержит UI на Qt,controller/управляет взаимодействиями,model/хранит данные и математику. - Паттерны: стратегия для выбора проекции (
model/projection.h), команда для undo/redo (controller/command.h), контроллер выступает фасадом для слоя представления. - Библиотека ядра: статическая
viewer_coreподключается к GUI и юнит-тестам, чтобы бизнес-логика оставалась независимой от UI. - Пайплайн рендеринга:
view/render_widget.cppсобирает матрицы MVP, рисует линии черезQPainterи умеет выводить сцену в offscreen для GIF-рекордера. - Безопасность: загрузчики кидают информативные
std::runtime_error, которые транслируются в статус-бар; настройки валидируются и ограничиваются при загрузке.
Импорт STL с дедупликацией вершин
auto getIndex = [&](float x, float y, float z) -> int {
Key k = Quantize(x, y, z);
auto it = map.find(k);
if (it != map.end()) return it->second;
int idx = static_cast<int>(out.vertices.size());
out.vertices.push_back(Vec3{x, y, z});
map.emplace(k, idx);
return idx;
};int i0 = getIndex(v[0], v[1], v[2]);
int i1 = getIndex(v[3], v[4], v[5]);
int i2 = getIndex(v[6], v[7], v[8]);
out.faces.push_back({i0, i1, i2});Undo/Redo через паттерн Command
void Controller::BeginInteraction() {
if (interacting_) return;
interacting_ = true;
before_ = TransformCmd::Capture(model_.transform());
}
void Controller::EndInteraction() {
if (!interacting_) return;
interacting_ = false;
auto after = TransformCmd::Capture(model_.transform());
if (std::memcmp(&before_, &after, sizeof(before_)) == 0) return;
auto cmd = std::make_unique<TransformCmd>();
cmd->before = before_;
cmd->after = after;
undo_.push_back(std::move(cmd));
redo_.clear();
}Адаптивный стиль рёбер в рендере
AdaptLineStyle(edge_count, base_color, settings.line_width, adapted_color,
adapted_width);
QPen pen(adapted_color);
pen.setWidthF(adapted_width);
pen.setStyle(settings.line_type == LineType::kDashed ? Qt::DashLine
: Qt::SolidLine);
pen.setCosmetic(true);
p->setPen(pen);meshgen grid <nx> <ny> <out.obj> [tri]строит регулярные сетки; опцияtriразбивает квады на треугольники.make gen_100kиmake gen_1mсоздают модели напрямую вsrc/build/models.- Цели
make formatиmake check_formatприменяют единый стиль изmaterials/linters/.clang-format.
- Базовые OBJ-файлы лежат в
models/и копируются вbuild/models/при конфигурации. - Приложение автоматически подхватывает содержимое
build/models/, чтобы новые сетки появлялись в выпадающем списке Samples. - Дополнительные тестовые или демонстрационные модели можно размещать рядом с существующими.
- Основная документация располагается в
dvi/. - Ключевой артефакт —
dvi/documentation.html: лёгкая, полностью гипертекстовая версия, которую удобно читать прямо в браузере. На фоне типичных PDF-файлов она выделяется интерактивным TOC, поиском и живыми ссылками на разделы. - При необходимости можно дополнить HTML версией в других форматах (PDF/DVI), но базовый канал доставки знаний — именно HTML.
- Просчет нормалей и предпросмотр затенения вместе с каркасом.
- Импорт glTF 2.0 с упрощением материалов.
- Headless-режим, позволяющий использовать движок для пакетного рендеринга.
- Плагинная система для пользовательских камер и скриптовых трансформаций.
С любовью Whiterage :3


