Магистерская диссертация · ВолГУ · 2026
MAGIS 3D
Проектирование и разработка web-сервиса обработки 3D-моделей
Бритков В.В. МОСм-241 Кафедра КНЭМ · ИМИТ 3d.gr8brite.ru
3
алгоритма
2
формата экспорта
8+
палитр
REST
API
01 / Актуальность
От плагина к web-сервису
Бакалаврская работа

Плагин для Blender: параметрические поверхности, экспорт OBJ/TXT, триангуляция сетки

⚠ Требует установки Blender (500 МБ+), ПК, локальной работы
Магистерская работа

Web-сервис в браузере: ноль установок, мультипользователь, REST API, социальные функции

✓ Открыть браузер → сразу работать на любом устройстве
  • Промышленность — CAD, прототипирование, 3D-печать
  • Наука — параметрическая геометрия, CSV-данные измерений
  • Образование — интерактивные графики в браузере без установки ПО
  • Проблема — Blender, Wolfram, GeoGebra требуют установки или платных подписок
02 / Постановка задачи
Цель и задачи работы
Цель

Проектирование и разработка многопользовательского web-сервиса для интерактивной 3D-визуализации параметрических поверхностей и данных CSV с экспортом моделей

Объект и предмет

Объект: клиент-серверные web-приложения для 3D-графики
Предмет: алгоритмы визуализации и обработки 3D-поверхностей в браузере

Задачи

  1. Провести анализ существующих решений в области browser-based 3D-визуализации
  2. Спроектировать клиент-серверную архитектуру web-сервиса
  3. Реализовать алгоритм дискретизации параметрических поверхностей
  4. Разработать модуль безопасного парсинга математических выражений
  5. Реализовать загрузку CSV и построение 3D-поверхности с текстурированием по высоте
  6. Реализовать экспорт в форматы OBJ и STL
  7. Разработать систему аутентификации и хранения сцен
  8. Провести функциональное тестирование сервиса
03 / Технологии
Технологический стек
3D рендеринг
Three.js
r128 CDN
Frontend
Vanilla JS
ES Classes, no bundler
Стили
HTML5 / CSS3
адаптивная вёрстка
Сервер
Node.js + Express
v18+ · ^4.19.2
База данных
SQLite 3
^5.1.7 · JSON сцены
Аутентификация
JWT + bcryptjs
HS256 · 7 дней TTL
Загрузка файлов
Multer
^2.1.1 · до 80 МБ
Инфраструктура
Nginx + PM2
SSL · Let's Encrypt
Управление камерой
OrbitControls
Three.js addon
Принцип: нулевая сборка — скрипты как <script src="...">, деплой — копирование файлов
04 / Проектирование
Архитектура системы
CLIENT — BROWSER Three.js r128 OrbitControls BufferGeometry AuthManager JWT localStorage login / register Generators SurfaceGenerator CSVSurfaceGenerator MathParser Managers SurfaceManager SceneManager SurfaceExporter UI Layer EventManager · ModalManager · ScenesWall https://3d.gr8brite.ru — Nginx + SSL REST / HTTPS SERVER — NODE.JS + EXPRESS /api/auth login / register /api/scenes GET POST likes /api/csv upload + parse Express.js · port 3005 · JWT middleware · bcryptjs SQLite users · scenes likes · comments Multer uploads CSV / TXT до 80 МБ PM2 process manager · автоперезапуск · логи Nginx · статика frontend · proxy /api/ → 3005
05 / Алгоритмы
Параметрические поверхности
X = f(u, v)   u ∈ [umin, umax]
Y = g(u, v)   v ∈ [vmin, vmax]
Z = h(u, v)
Пример — Тор
X = (R + r·cos v)·cos u
Y = (R + r·cos v)·sin u
Z = r·sin(v)
Шаги
  • Дискретизация сетки (u,v)
  • Вычисление вершин
  • Триангуляция quad→2▲
  • computeVertexNormals()
Пресеты: тор, сфера, параболоид, клейн, катеноид, геликоид, суперторус…
// Дискретизация + триангуляция
for (let i = 0; i <= uSeg; i++) {
  for (let j = 0; j <= vSeg; j++) {
    const u = uMin + i * uStep;
    const v = vMin + j * vStep;
    vertices.push(
      parser.evaluate(eqX, {u,v}) * scale,
      parser.evaluate(eqY, {u,v}) * scale,
      parser.evaluate(eqZ, {u,v}) * scale
    );
  }
}
// Quad → два треугольника
for (let i = 0; i < uSeg; i++) {
  for (let j = 0; j < vSeg; j++) {
    const a = i*(vSeg+1)+j, b=a+1,
          c = (i+1)*(vSeg+1)+j, d=c+1;
    indices.push(a,b,d, a,d,c);
  }
}
geometry.computeVertexNormals();
06 / Алгоритмы
Безопасный математический парсер
Почему не eval()?
  • Выполняет произвольный JS-код
  • XSS / RCE уязвимость
  • Нельзя whitelist-ить функции
Реализованный алгоритм
Выражение Токенизация Shunting-Yard RPN стек Результат
Whitelist функций
sin, cos, tan, asin, acos, atan, atan2
sinh, cosh, tanh · sqrt, cbrt, pow
exp, log, log10, log2 · abs, ceil, floor
round, sign, min, max · pi, e
evaluate(expression, variables = {}) {
  let expr = expression.trim();
  // Препроцессинг: ** → ^, Math. → ''
  expr = this.preprocessExpression(expr);
  expr = this.replaceConstants(expr);   // pi→3.14…
  expr = this.validateExpression(expr); // whitelist
  return this.evaluateExpression(expr, variables);
}

tokenize(expr) {
  // числа, функции из whitelist, переменные u/v,
  // операторы +−*/^, скобки ()
  // → массив токенов [{type, value}, ...]
}

shuntingYard(tokens) {
  // алгоритм Дейкстры: стек операторов
  // + очередь вывода → постфиксная запись
  // приоритеты: ^ > *,/ > +,−
}

evaluateRPN(rpn, variables) {
  // стековый калькулятор → число
}
07 / Алгоритмы
CSV → 3D поверхность
1Загрузка multipart/csvFile → Multer → disk
2Автоопределение разделителя ; \t , |
3Определение столбцов x,y,z — по заголовкам или эвристике
4Построение сетки nx × ny, пропуски → z=0
5Ответ JSON → клиент → Three.js меш
CSV (x, y, z) → Three.js (x, z, y)
Ось Y Three.js = высота → CSV z определяет высоту
// Сервер: buildGrid(points)
const xs = [...new Set(pts.map(p=>p[0]))].sort((a,b)=>a-b);
const ys = [...new Set(pts.map(p=>p[1]))].sort((a,b)=>a-b);
const grid = new Array(xs.length * ys.length).fill(null);
for (const [x, y, z] of pts) {
  const i = xs.indexOf(x), j = ys.indexOf(y);
  grid[i * ys.length + j] = [x, y, z];
}
// Пропуски → z = 0
const filled = grid.map((p, idx) => p ?? [
  xs[Math.floor(idx/ys.length)],
  ys[idx % ys.length], 0
]);

// Клиент: маппинг координат
const [cx, cy, cz] = grid[i * ny + j];
vertices.push(cx, cz, cy); // CSV(x,y,z)→THREEjs(x,z,y)
08 / Визуализация
Текстурирование по высоте
t = (zij − zmin) / (zmax − zmin)
Нормированный параметр t ∈ [0, 1] определяет цвет вершины в выбранной палитре. WebGL интерполирует цвет по треугольникам.
viridis
plasma
inferno
coolwarm
rainbow
hot
cool
grayscale
// Кусочно-линейная интерполяция палитры
_lerp(t, stops) {
  for (let i = 0; i < stops.length - 1; i++) {
    const [t0, c0] = stops[i];
    const [t1, c1] = stops[i + 1];
    if (t >= t0 && t <= t1) {
      const f = (t - t0) / (t1 - t0);
      return [
        c0[0] + (c1[0]-c0[0]) * f,
        c0[1] + (c1[1]-c0[1]) * f,
        c0[2] + (c1[2]-c0[2]) * f
      ];
    }
  }
}
_viridis(t) {
  return this._lerp(t, [
    [0.00, [0.267, 0.005, 0.329]],
    [0.25, [0.230, 0.322, 0.546]],
    [0.50, [0.128, 0.566, 0.551]],
    [0.75, [0.369, 0.788, 0.384]],
    [1.00, [0.993, 0.906, 0.144]]
  ]);
}
09 / Экспорт
Экспорт моделей: OBJ и STL
ASCII OBJ
v x y z   ← вершины
vn nx ny nz ← нормали
g имя_поверхности
f v1//n v2//n v3//n ← грани
ASCII STL
solid name
  facet normal nx ny nz
    outer loop
      vertex x y z (×3)
    endloop  endfacet
endsolid name
Сферическая инверсия OBJ
P′ = C + R² · (P − C) / |P − C|²

C = центр масс, R = max расстояние → топологическая инверсия модели

exportSurfaceAsOBJ(surface) {
  const {vertices: v, triangleIndices: idx} = surface;
  let obj = `# Surface: ${surface.name}\n`;
  obj += `# ${new Date().toISOString()}\n\n`;

  for (let i = 0; i < v.length; i += 3)
    obj += `v ${v[i].toFixed(6)} `
         + `${v[i+1].toFixed(6)} `
         + `${v[i+2].toFixed(6)}\n`;

  const normals = this.calculateNormals(v, idx);
  for (let i = 0; i < normals.length; i += 3)
    obj += `vn ${normals[i].toFixed(6)} `
         + `${normals[i+1].toFixed(6)} `
         + `${normals[i+2].toFixed(6)}\n`;

  obj += `\ng ${surface.name}\n`;
  for (let i = 0; i < idx.length; i += 3) {
    const a=idx[i]+1, b=idx[i+1]+1, c=idx[i+2]+1;
    obj += `f ${a}//${a} ${b}//${b} ${c}//${c}\n`;
  }
  return obj;
}
10 / Безопасность
Аутентификация и база данных
JWT аутентификация
  • Алгоритм HS256, TTL 7 дней
  • Bearer token в заголовке Authorization
  • Middleware проверки для защищённых маршрутов
  • Хранение в localStorage + автовосстановление сессии
bcryptjs пароли
  • 10 раундов соления при регистрации
  • Сравнение через bcrypt.compare()
  • Пароль в открытом виде никогда не хранится
Схема SQLite
users(id, username, email, password_hash)
scenes(id, user_id, title, scene_data JSON, preview_base64)
likes(user_id, scene_id) UNIQUE
comments(id, user_id, scene_id, content, created_at)
// Регистрация
const hash = await bcrypt.hash(password, 10);
db.run(`INSERT INTO users
  (username,email,password_hash)
  VALUES (?,?,?)`, [name,email,hash]);

// Вход
const user = db.get(`SELECT * FROM users
  WHERE email = ?`, [email]);
const ok = await bcrypt.compare(password, user.hash);
if (ok) {
  const token = jwt.sign(
    { userId: user.id, email: user.email },
    process.env.JWT_SECRET,
    { expiresIn: '7d' }
  );
  res.json({ token });
}
Направления развития
  • HttpOnly Secure cookie вместо localStorage (XSS)
  • Rate limiting + Helmet.js
  • Refresh token для продления сессии
11 / Тестирование
Результаты функционального тестирования
Авторизация (вход, регистрация, гость)
Параметрическая поверхность — тор, сфера, параболоид
Загрузка CSV wave_surface.csv (25×25 точек)
Визуализация CSV — виридис, плазма, инферно
Экспорт OBJ с нормалями и именем поверхности
Экспорт STL — ASCII формат, facet normal
Сохранение и загрузка сцены через REST API
Галерея сцен — лайки, комментарии
Адаптивный UI — mobile 375px, tablet 768px
Виды камеры — FRONT, RIGHT, TOP, PERSP, ORTHO
OrbitControls — вращение, масштаб, перемещение
PUT/DELETE сцен — не реализованы (расхождение README)
Пройдено: 11
Замечания: 1
Автоматизация: Playwright MCP · 8 скриншотов · консоль + сетевые логи
12 / Итоги
Результаты работы
  • Разработан и развёрнут полнофункциональный web-сервис на https://3d.gr8brite.ru
  • Реализовано 3 алгоритма трёхмерной визуализации: параметрические поверхности, CSV-сетка, математический парсер
  • Реализован экспорт в форматы OBJ и STL с вычислением нормалей и сферической инверсией
  • Разработана многопользовательская система с JWT + bcrypt, хранением сцен, галереей, лайками и комментариями
  • Адаптивный интерфейс — breakpoints 480, 768, 1024, 1400px; OrbitControls; 5 видов камеры
  • Работа является развитием бакалаврской диссертации — от Blender-плагина до zero-install браузерного сервиса
13
модулей JS
8
палитр цвета
5
REST маршрутов
4
таблицы БД

Демо-сервис

https://3d.gr8brite.ru

Спасибо
Готов ответить на вопросы

01 / 13