Фиксация осей перемещения и вращения

Библиотека Cannon.js предоставляет мощные средства для физического моделирования в браузере, включая точное управление объектами в 3D-пространстве. Контроль над движением объектов осуществляется через свойства тел и ограничения, позволяя фиксировать отдельные оси трансляции или вращения для создания сложных механизмов, шарниров и ограниченных движений.


Свойства тел для ограничения движения

Каждое тело в Cannon.js представлено объектом CANNON.Body, который обладает набором ключевых свойств:

  • mass – масса тела. Масса равная нулю делает объект статическим.
  • position – вектор позиции объекта в пространстве.
  • velocity – линейная скорость.
  • angularVelocity – угловая скорость.
  • linearFactor – вектор (x, y, z), задающий возможность движения по каждой оси. Значение 1 разрешает движение, 0 запрещает.
  • angularFactor – вектор (x, y, z), задающий возможность вращения вокруг каждой оси. Аналогично, 1 разрешает вращение, 0 запрещает.

Пример фиксации движения по оси Y и вращения вокруг оси Z:

const body = new CANNON.Body({ mass: 1 });
body.linearFactor.set(1, 0, 1);   // фиксируем движение по Y
body.angularFactor.set(1, 1, 0);  // фиксируем вращение вокруг Z

Использование этих свойств удобно для создания объектов, которые должны двигаться только в определённой плоскости или вращаться только вокруг конкретных осей.


Ограничения (Constraints)

Для более сложных взаимодействий и фиксации можно использовать ограничения (constraints). Cannon.js предоставляет несколько видов ограничений:

  1. CANNON.LockConstraint Полностью блокирует все движения между двумя телами, фиксируя их взаимное положение и ориентацию.

    const constraint = new CANNON.LockConstraint(bodyA, bodyB);
    world.addConstraint(constraint);
  2. CANNON.HingeConstraint Позволяет вращение вокруг одной оси, фиксируя все остальные. Подходит для дверей, шестерёнок, рычагов.

    const hinge = new CANNON.HingeConstraint(bodyA, bodyB, {
      pivotA: new CANNON.Vec3(0, 0, 0),
      axisA: new CANNON.Vec3(0, 1, 0),
      pivotB: new CANNON.Vec3(0, 0, 0),
      axisB: new CANNON.Vec3(0, 1, 0)
    });
    world.addConstraint(hinge);
  3. CANNON.PointToPointConstraint Ограничивает расстояние между точками двух тел, при этом остаётся возможным вращение вокруг этой точки. Полезно для подвесных объектов.

    const p2p = new CANNON.PointToPointConstraint(bodyA, new CANNON.Vec3(0,1,0), bodyB, new CANNON.Vec3(0,0,0));
    world.addConstraint(p2p);

Комбинирование линейных и угловых факторов с ограничениями

Для точного контроля можно одновременно использовать linearFactor, angularFactor и ограничения. Например, если требуется, чтобы объект двигался только по оси X и вращался только вокруг оси Y:

body.linearFactor.set(1, 0, 0);
body.angularFactor.set(0, 1, 0);

// дополнительно фиксируем объект к другому телу по определённой оси
const hinge = new CANNON.HingeConstraint(body, staticBody, {
    pivotA: new CANNON.Vec3(0,0,0),
    axisA: new CANNON.Vec3(0,1,0)
});
world.addConstraint(hinge);

Такое сочетание обеспечивает максимальную гибкость: linearFactor и angularFactor задают ограничения на уровне тела, а constraints позволяют создавать механические связи между телами.


Практические советы

  • Статические объекты: всегда задавать mass = 0, а для динамических тел использовать linearFactor и angularFactor для ограничения движения.
  • Производительность: применение constraints увеличивает нагрузку на физический движок. Использовать только там, где требуется точная фиксация.
  • Комбинация осей: для фиксации нескольких осей можно использовать векторные множители (x, y, z), что даёт полный контроль над трансляцией и вращением.
  • Подвижные механизмы: HingeConstraint и PointToPointConstraint подходят для создания рычажных систем, маятников и дверей, где необходима точная ось вращения.

Взаимодействие с миром

Физический мир Cannon.js задаётся объектом CANNON.World, который управляет всеми телами и constraints:

const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
world.addBody(body);

Фиксированные оси работают внутри шага интеграции:

world.step(1/60);

Все ограничения и factors применяются на каждом шаге, обеспечивая предсказуемое движение объектов с ограниченными осями.


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