Дипломная работа

Magis3D

Проектирование и разработка web-сервиса обработки 3D-моделей

Three.jsExpressSQLiteOBJ/STLCSV
QR-код проекта Magis3D

Ссылка на проект

https://3d.gr8brite.ru/
Логика проекта

Что решает Magis3D

Рабочая область Magis3D
Рабочая область Magis3D
  • создание 3D-поверхностей по формулам;
  • загрузка CSV/TXT и построение сетки;
  • импорт OBJ-моделей в сцену;
  • сохранение и экспорт результата.

Проект показывает полный путь от входных данных до готовой 3D-сцены.

Пользовательский сценарий

Путь пользователя в системе

  • пользователь входит в систему или продолжает работу как гость;
  • в рабочей области создаёт поверхность, загружает файл или импортирует модель;
  • результат обрабатывается в браузере и сразу отображается в 3D-окне;
  • готовая сцена сохраняется в базе или выгружается в файл.
Последовательность действий
ПользовательWeb UIСервисSQLiteвход / регистрациясоздание сценысохранение данныхответ и обновление галереи
Авторизация

Стартовый экран

Вход, регистрация и гостевой режим
Вход, регистрация и гостевой режим
  • аккаунт нужен для сохранения сцен;
  • гостевой режим оставляет быстрый доступ;
  • после входа открывается рабочая область.
Регистрация

Создание аккаунта

Форма регистрации пользователя
Форма регистрации пользователя
  • производится проверка полей до создания аккаунта;
  • email приводится к единому виду;
  • пароль не сохраняется открытым текстом;
  • после регистрации выдаётся токен сессии.
Код регистрации

Проверка данных на сервере

backend/src/routes/auth.js
router.post('/register', async (req, res) => {
  const { name, email, password } = req.body || {};

  // Производится проверка обязательных полей.
  if (!name || !email || !password) {
    return res.status(400).json({ error: 'Заполните все поля' });
  }

  // Email нормализуется перед записью и сравнением.
  const normalizedEmail = String(email).toLowerCase().trim();

  // Пароль хранится только в виде bcrypt-хэша.
  const passwordHash = await bcrypt.hash(String(password), 10);

  // После создания аккаунта формируется токен сессии.
  const token = createToken(user);
  return res.status(201).json({ user, token });
});

Валидация выполняется на backend, поэтому её нельзя обойти изменением интерфейса.

Пароль преобразуется в bcrypt-хэш, а клиент получает JWT для дальнейших запросов.

Сессия

Восстановление входа

frontend/js/core/authManager.js
const savedToken = localStorage.getItem('authToken');

// Если токен есть, выполняется запрос /auth/me.
if (savedToken) {
  this.fetchMe(savedToken)
    .then(user => {
      // Сессия восстановлена без повторного ввода пароля.
      this.currentUser = user;
      this.isGuest = false;
      this.showApp();
    })
    .catch(() => {
      // Некорректный токен удаляется из браузера.
      localStorage.removeItem('authToken');
      localStorage.removeItem('currentUser');
    });
}

Приложение проверяет сохранённый токен.

Пользователь не вводит пароль каждый раз.

При ошибке сессия безопасно сбрасывается.

Рабочая область

Окно рендера и панели управления

3D-viewer, параметры и действия со сценой
3D-viewer, параметры и действия со сценой
  • рендер занимает центральную часть интерфейса;
  • панели отвечают за создание, импорт, сохранение и экспорт;
  • изменения сразу отображаются в 3D-окне.
Инициализация

Запуск модулей приложения

frontend/js/core/app.js
initMainApp() {
  // Создаётся viewer на базе Three.js.
  this.viewer = new SurfaceViewer('viewer-container', this.authManager);

  // Менеджер поверхностей связывается с областью рендера.
  this.surfaceManager = new SurfaceManager(this.viewer, this.authManager);
  this.viewer.setSurfaceManager(this.surfaceManager);

  // Отдельные классы отвечают за сцены, генерацию и OBJ.
  this.sceneManager = new SceneManager(this.authManager, this.surfaceManager);
  this.generator = new SurfaceGenerator();
  this.objProcessor = new OBJModelProcessor();
}

Viewer отвечает за отображение сцены.

SurfaceManager управляет объектами.

Генератор и OBJ-процессор вынесены отдельно.

Формулы

Параметрическая поверхность

Результат генерации по формулам
Результат генерации по формулам
  • задаются диапазоны параметров u и v;
  • для каждой точки вычисляются x, y, z;
  • точки соединяются в треугольную сетку;
  • готовая геометрия передаётся в Three.js.
Код генерации

Формулы превращаются в 3D-сетку

frontend/js/generators/surfaceGenerator.js
// Для каждого узла параметрической сетки вычисляются координаты.
for (let i = 0; i <= uSeg; i++) {
  for (let j = 0; j <= vSeg; j++) {
    const u = uMin + i * uStep;
    const v = vMin + j * vStep;
    const x = this.parser.evaluate(eqX, { u, v }) * scale;
    const y = this.parser.evaluate(eqY, { u, v }) * scale;
    const z = this.parser.evaluate(eqZ, { u, v }) * scale;
    vertices.push(x, y, z);
  }
}

// Соседние точки объединяются в треугольники для WebGL.
triangleIndices.push(a, b, d);
triangleIndices.push(a, d, c);

Формулы вычисляются много раз по сетке.

Результат хранится как массив вершин.

Треугольники нужны для WebGL-рендера.

CSV/TXT

Построение поверхности по таблице

Поверхность, построенная по данным CSV
Поверхность, построенная по данным CSV
  • файл загружается на сервер;
  • разделитель определяется автоматически;
  • из строк выбираются координаты X/Y/Z;
  • точки преобразуются в поверхность.
Код CSV

Ограничение формата и разбор координат

backend/src/routes/csv.js
const upload = multer({
  fileFilter: (req, file, cb) => {
    // Загрузка разрешена только для CSV/TXT файлов.
    if (/\.(csv|txt)$/i.test(file.originalname)) cb(null, true);
    else cb(new Error('Допустимы только CSV/TXT файлы'));
  },
  limits: { fileSize: 80 * 1024 * 1024 }
});

// Строки файла преобразуются в числовые X/Y/Z точки.
const rows = lines.map(line => parseCSVLine(line, delim));
const { indices, hasHeader } = resolveXYZColumns(rows, delim);

Сервер принимает только нужные типы файлов.

Есть ограничение размера загрузки.

Координаты приводятся к внутреннему формату.

OBJ импорт

Готовая 3D-модель в сцене

Импорт OBJ-модели
Импорт OBJ-модели
  • OBJ содержит вершины и грани модели;
  • модель разбирается в браузере;
  • геометрия приводится к формату сцены;
  • объект отображается вместе с остальными элементами.
Код OBJ

Разбор вершин и граней

frontend/js/processors/objModelProcessor.js
lines.forEach((line) => {
  const parts = line.trim().split(/\s+/);

  // Строки v содержат координаты вершин.
  if (parts[0] === 'v') {
    positions.push(Number(parts[1]), Number(parts[2]), Number(parts[3]));
  }

  // Строки f содержат грани модели.
  if (parts[0] === 'f') {
    const face = parts.slice(1).map(token => this.parseFaceIndex(token));
    for (let i = 1; i < face.length - 1; i++) {
      triangles.push(face[0], face[i], face[i + 1]);
    }
  }
});

Вершины попадают в массив координат.

Грани разбиваются на треугольники.

После разбора модель можно рендерить.

Обработка OBJ

Нормализация модели

Проверка импортированной геометрии
Проверка импортированной геометрии
  • производится проверка индексов граней;
  • повторяющиеся вершины объединяются;
  • рассчитываются границы и размеры модели;
  • модель становится совместима со сценой.
Сохранение

Запись сцены пользователя

Сохранение созданной сцены
Сохранение созданной сцены
  • сохранение доступно авторизованному пользователю;
  • сцена связывается с аккаунтом;
  • данные сцены хранятся как JSON;
  • превью используется для галереи.
Код сохранения

Сцена записывается в SQLite

backend/src/routes/scenes.js
router.post('/', authenticateToken, async (req, res) => {
  const { title, sceneData, previewImage } = req.body;

  // Сохранение разрешено только после авторизации.
  if (!title || !sceneData) {
    return res.status(400).json({ error: 'Название и данные обязательны' });
  }

  // Сцена связывается с id текущего пользователя.
  await run(`INSERT INTO scenes
    (user_id, title, scene_data, preview_image)
    VALUES (?, ?, ?, ?)`,
    [req.user.id, title.trim(), JSON.stringify(sceneData), previewImage]
  );
});

Middleware определяет пользователя по JWT.

Данные сцены сериализуются в JSON.

Запись можно восстановить при открытии.

Галерея

Публичные сцены из базы

Стена сохранённых сцен
Стена сохранённых сцен
  • выводятся публичные сцены;
  • показываются автор, дата и превью;
  • пользователь может открыть готовый результат.
Экспорт

Выгрузка результата

Окно выбора формата экспорта
Окно выбора формата экспорта
  • экспорт разрешён только для корректной геометрии;
  • OBJ подходит для дальнейшего редактирования;
  • STL подходит для инженерных сценариев;
  • файл формируется и скачивается из браузера.
Код экспорта

OBJ и STL формируются из геометрии

frontend/js/core/surfaceExporter.js
exportSurface(surface, format) {
  // Экспорт разрешён только для поверхности с геометрией.
  if (!surface.vertices || !surface.triangleIndices) {
    throw new Error('Некорректные данные поверхности');
  }

  switch (format) {
    case 'obj':
      content = this.exportSurfaceAsOBJ(surface);
      filename = `${this.sanitizeFilename(surface.name)}.obj`;
      break;
    case 'stl':
      content = this.exportSurfaceAsSTL(surface);
      filename = `${this.sanitizeFilename(surface.name)}.stl`;
      break;
  }

  this.downloadFile(content, filename, mimeType);
}

Сначала выполняется проверка наличия вершин.

Формат выбирается через switch.

Готовый файл отдаётся пользователю.

Адаптивность

Интерфейс на мобильном экране

Мобильное отображение сервиса
Мобильное отображение сервиса
  • панели перестраиваются под узкий экран;
  • основные действия остаются доступны;
  • 3D-viewer остаётся главным элементом;
  • презентация подготовлена в 4:3 под проектор.
Архитектура

UML-диаграмма компонентов проекта

Компоненты системы
«component»Web UI«component»Three.js Viewer«component»AuthManager«component»SurfaceManager«component»SceneManager«component»Express API«component»CSV Parser«component»JWT Auth«component»SQLite«component»OBJ/STL/JSONrenderlogintoolssceneapicsvtokensaveexport
  • frontend отделён от backend, поэтому интерфейс и API можно развивать независимо;
  • Three.js отвечает только за визуализацию, а не за бизнес-логику;
  • авторизация, сохранение и экспорт разделены на отдельные сервисы;
  • SQLite хранит пользователей и сцены в структурированном виде.

На слайде показаны реальные зависимости, а не декоративные блоки.

Итог

Результат дипломной работы

  • реализован web-сервис для интерактивной работы с 3D-сценами;
  • поддержаны формулы, CSV/TXT и импорт OBJ;
  • добавлены аккаунты, сохранение сцен и публичная галерея;
  • реализован экспорт результата в OBJ/STL.

Полный цикл: ввод данных → обработка → визуализация → хранение → выгрузка результата.