Структура пакета и точки входа

Oimo.js — физический движок для моделирования твёрдых тел, написанный на JavaScript и ориентированный на использование в браузере и в среде Node.js. Архитектура пакета построена по модульному принципу: каждая подсистема (математика, формы столкновений, динамика, ограничения и широкофазная проверка) выделена в отдельный набор модулей. Это упрощает сопровождение, оптимизацию и сборку под разные цели.

Структура дистрибутива обычно включает:

  • исходные модули (ES6 или UMD);
  • сборочный файл для браузера (минифицированный и неминифицированный);
  • описание зависимостей (package.json);
  • примеры и тесты;
  • конфигурации сборщика (например, Rollup или Webpack).

Пакет распространяется через npm под именем oimo, что позволяет подключать его как зависимость в современных фронтенд-проектах.


Форматы поставки и сборки

UMD-сборка

UMD-версия ориентирована на использование через <script> в браузере. После подключения глобальная переменная OIMO становится точкой доступа ко всем классам движка.

Особенности:

  • не требует сборщика;
  • подходит для быстрых прототипов;
  • предоставляет доступ к API через глобальное пространство имён.

В этом режиме структура пакета «сворачивается» в единый файл, где все модули объединены в один namespace.

ES-модули

Современные версии Oimo.js поддерживают модульную систему ES6. Это позволяет:

  • импортировать только необходимые части движка;
  • уменьшать итоговый размер бандла;
  • использовать tree-shaking;
  • интегрировать движок в сложные SPA-приложения.

Пример точечного импорта:

import { World, RigidBody, Vec3 } from 'oimo';

В этом случае точкой входа становится основной экспорт пакета, который агрегирует ключевые классы.


Точка входа пакета

В package.json определяется поле main и/или module, указывающее на главный файл сборки. Именно этот файл выполняет роль центральной точки входа.

Типичная схема:

  • main → UMD или CommonJS-сборка;
  • module → ES-модульная версия;
  • browser → оптимизированная сборка для браузера.

Главный файл выполняет следующие задачи:

  1. Импортирует внутренние модули.
  2. Формирует публичный API.
  3. Экспортирует ключевые классы и утилиты.

Таким образом, внешнее приложение взаимодействует не с внутренней структурой движка, а с агрегированным интерфейсом.


Внутренняя модульная структура

Логическая структура движка делится на несколько подсистем.

1. Математическое ядро

Каталог с математическими примитивами включает:

  • векторы (Vec3),
  • матрицы (Mat3, Mat4),
  • кватернионы,
  • вспомогательные функции преобразований.

Эти модули независимы от динамики и используются всеми остальными подсистемами.

Основные задачи:

  • операции над векторами;
  • нормализация;
  • преобразование координат;
  • расчёт инерции и вращения.

2. Геометрия и формы столкновений

Подсистема shapes содержит реализации:

  • BoxShape;
  • SphereShape;
  • CylinderShape;
  • CapsuleShape;
  • ConvexHull и др.

Каждая форма инкапсулирует:

  • геометрические параметры;
  • вычисление AABB (Axis-Aligned Bounding Box);
  • расчёт локальной инерции;
  • поддержку алгоритмов столкновений.

Формы не обладают динамикой — они используются телами (RigidBody).


3. Динамические тела

Каталог динамики включает:

  • RigidBody;
  • BodyConfig;
  • типы тел (dynamic, static, kinematic);
  • обработку массы и инерции.

RigidBody объединяет:

  • форму;
  • трансформацию;
  • скорость;
  • угловую скорость;
  • силу и момент.

Именно здесь реализуется интеграция движения.


4. Мир (World)

Класс World — центральный координационный элемент. Он отвечает за:

  • хранение тел;
  • обновление физического шага;
  • гравитацию;
  • обработку столкновений;
  • решение ограничений.

Структурно World зависит от всех подсистем, но внешнему коду достаточно работать только с ним.


5. Широкофазная проверка (BroadPhase)

Подсистема BroadPhase выполняет первичный отбор потенциально сталкивающихся тел.

Внутри пакета могут использоваться:

  • Sweep and Prune;
  • динамические деревья;
  • AABB-проверки.

BroadPhase работает с bounding box’ами и передаёт кандидатов в узкофазный алгоритм.


6. Узкофазная проверка (NarrowPhase)

NarrowPhase реализует:

  • алгоритмы GJK;
  • EPA;
  • SAT;
  • генерацию контактных точек.

Эти модули глубоко интегрированы с геометрией и математическим ядром.


7. Ограничения и соединения

Подсистема constraints реализует:

  • шарнирные соединения;
  • пружины;
  • фиксацию расстояния;
  • ограничение вращения.

Каждое ограничение представлено отдельным классом, наследующим базовый тип Constraint.


Связь внутренних модулей

Взаимодействие модулей строится по следующей схеме:

Math → Shapes → RigidBody → World
                ↘
              BroadPhase → NarrowPhase → Solver

Такое разделение обеспечивает:

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

Экспортируемый API

Главная точка входа формирует публичный интерфейс, экспортируя:

  • World
  • RigidBody
  • Shape-классы
  • математические структуры
  • типы ограничений

Публичный API скрывает:

  • внутренние оптимизации;
  • низкоуровневые структуры данных;
  • промежуточные классы столкновений;
  • служебные менеджеры.

Это снижает риск некорректного использования движка.


Организация исходников

Типичная структура исходного кода может выглядеть так:

src/
 ├── core/
 │    ├── World.js
 │    ├── RigidBody.js
 │
 ├── math/
 │    ├── Vec3.js
 │    ├── Mat3.js
 │
 ├── collision/
 │    ├── broadphase/
 │    ├── narrowphase/
 │
 ├── shape/
 │    ├── Box.js
 │    ├── Sphere.js
 │
 ├── constraint/
 │
 └── utils/

Такое деление позволяет:

  • поддерживать чистую архитектуру;
  • тестировать подсистемы изолированно;
  • масштабировать проект.

Точка входа в браузере

При использовании UMD-сборки:

<script src="oimo.min.js"></script>
<script>
    const world = new OIMO.World();
</script>

В этом случае глобальный объект OIMO формируется главным файлом сборки.


Точка входа в модульной среде

При использовании ES-модулей:

import { World } from 'oimo';

const world = new World();

Здесь точка входа определяется системой модулей и конфигурацией сборщика.


Связь с экосистемой JavaScript

Oimo.js часто используется совместно с графическими библиотеками, например:

  • Three.js
  • Babylon.js

В таких проектах структура пакета и корректная точка входа особенно важны, поскольку физический движок интегрируется в уже существующую архитектуру рендеринга.


Расширяемость структуры

Благодаря модульной организации возможно:

  • добавление новых форм столкновений;
  • внедрение альтернативных алгоритмов broadphase;
  • модификация солвера ограничений;
  • оптимизация математических операций.

Расширение осуществляется либо через форк проекта, либо через подключение пользовательских модулей поверх публичного API.


Управление зависимостями

Oimo.js не имеет тяжёлых внешних зависимостей, что упрощает:

  • переносимость;
  • контроль размера бандла;
  • использование в офлайн-проектах;
  • встраивание в игровые движки.

Весь функционал сосредоточен внутри пакета, а точка входа лишь агрегирует экспорт.


Архитектурные принципы

Структура пакета строится на следующих принципах:

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

Такая организация делает движок предсказуемым для разработчиков и удобным для анализа внутренней логики.


Роль точки входа в производительности

Главный файл сборки влияет на:

  • порядок инициализации классов;
  • стратегию ленивой загрузки;
  • совместимость с tree-shaking;
  • минимизацию размера финального пакета.

Грамотно организованная точка входа позволяет:

  • исключать неиспользуемые части;
  • разделять код на чанки;
  • ускорять загрузку веб-приложения.

Структура пакета Oimo.js отражает баланс между низкоуровневой физической математикой и удобным публичным API. Чёткое разделение подсистем, продуманная точка входа и поддержка разных форматов сборки обеспечивают гибкость интеграции в современные JavaScript-проекты различной сложности.