UniversalJoint в Oimo.js представляет собой тип соединения, позволяющий двум телам вращаться относительно друг друга по двум взаимно перпендикулярным осям. Это один из наиболее гибких видов суставов в физическом движке, используемый для моделирования шарнирных соединений, карданных валов и других механизмов с двойной степенью свободы вращения.
Два независимых вращательных степеней свободы UniversalJoint позволяет телу вращаться вокруг двух осей, обычно называемых осью A и осью B, которые перпендикулярны друг другу в локальной системе координат первого тела.
Ограничения вращения (Limit) Для каждой оси можно задать минимальный и максимальный угол поворота. Это важно для моделирования реальных механизмов, где угол поворота ограничен конструкцией.
Моторизация (Motor) Для обеих осей возможно подключение моторов, что позволяет задавать целевую скорость вращения или усилие (torque). Это применяется в робототехнике или симуляции приводов.
Применение к динамическим и статическим телам Сустав можно соединять как с подвижными, так и с неподвижными телами, создавая устойчивые и управляемые механические системы.
Для создания универсального сустава используется конструктор
OIMO.UniversalJoint. Основная сигнатура:
new OIMO.UniversalJoint({
bodyA: rigidBodyA,
bodyB: rigidBodyB,
anchor: [x, y, z],
axis1: [x1, y1, z1],
axis2: [x2, y2, z2],
lowerLimit1: -Math.PI / 4,
upperLimit1: Math.PI / 4,
lowerLimit2: -Math.PI / 6,
upperLimit2: Math.PI / 6,
motor1: true,
motor2: false,
maxForce1: 10,
maxForce2: 0
});
Пояснение параметров:
bodyA и bodyB — тела, соединяемые
суставом.anchor — точка в пространстве, в которой сустав
закрепляется. Обычно задаётся в глобальных координатах сцены.axis1 и axis2 — направления осей вращения
в локальной системе bodyA. Оси должны быть
перпендикулярны.lowerLimit1 / upperLimit1 и
lowerLimit2 / upperLimit2 — минимальные и
максимальные углы вращения для первой и второй оси.motor1 / motor2 — включение мотора для
каждой оси.maxForce1 / maxForce2 — максимальная сила,
которую может развивать мотор на соответствующей оси.UniversalJoint позволяет тонко настраивать физические ограничения:
joint.setLimits1(-Math.PI/4, Math.PI/4);
joint.setLimits2(-Math.PI/6, Math.PI/6);
joint.enableMotor1(true, 5); // включение мотора с целевой скоростью 5 рад/с
joint.enableMotor2(false, 0); // мотор выключен
setLimits1 задает границы вращения для первой
оси, аналогично setLimits2 для второй.enableMotor1 позволяет управлять вращением по оси
через мотор с заданной скоростью.maxForce определяет, насколько сильным будет мотор;
если сила слишком мала, тело не сможет достичь заданной скорости.UniversalJoint работает корректно только с динамическими телами. Для статического тела (например, фиксированного основания) один из компонентов может быть статическим, что позволит телу свободно вращаться в пределах ограничений:
const ground = new OIMO.Body({ type: "static" });
const box = new OIMO.Body({ type: "dynamic", size: [1,1,1] });
const joint = new OIMO.UniversalJoint({
bodyA: ground,
bodyB: box,
anchor: [0, 0.5, 0],
axis1: [1, 0, 0],
axis2: [0, 0, 1],
lowerLimit1: -Math.PI/4,
upperLimit1: Math.PI/4,
lowerLimit2: -Math.PI/6,
upperLimit2: Math.PI/6
});
В этом примере коробка (box) может вращаться вокруг двух
осей относительно неподвижного основания.
axis1 и
axis2. Нарушение этого условия приводит к нестабильной
симуляции.UniversalJoint обеспечивает точное управление вращением с ограничениями и моторами, сочетая гибкость и реалистичность физической симуляции. Правильная настройка осей, ограничений и сил позволяет создавать сложные механизмы, сохраняя стабильность и предсказуемость движения.