В физическом движке Oimo.js сериализация и десериализация представляют собой процессы сохранения и восстановления состояния физического мира. Эти механизмы необходимы для сохранения игры, создания контрольных точек (checkpoints) или передачи состояния между клиентом и сервером.
В контексте Oimo.js состояние мира включает:
RigidBody): позиции, ориентации,
линейные и угловые скорости.Constraint): соединения
тел, их параметры.World):
гравитация, шаг интеграции, коэффициенты силы трения и упругости.Oimo.js не предоставляет встроенного метода
world.toJSON(), поэтому сериализация требует ручного обхода
объектов. Общая схема:
const serializedWorld = {
bodies: [],
constraints: [],
settings: {
gravity: [world.gravity.x, world.gravity.y, world.gravity.z],
timestep: world.timeStep
}
};
world.bodies.forEach(body => {
serializedWorld.bodies.push({
name: body.name,
type: body.type, // dynamic, static, kinematic
position: [body.position.x, body.position.y, body.position.z],
rotation: [body.quaternion.x, body.quaternion.y, body.quaternion.z, body.quaternion.w],
linearVelocity: [body.linearVelocity.x, body.linearVelocity.y, body.linearVelocity.z],
angularVelocity: [body.angularVelocity.x, body.angularVelocity.y, body.angularVelocity.z],
shapes: body.shapes.map(shape => ({
type: shape.type,
size: shape.size,
friction: shape.friction,
restitution: shape.restitution
}))
});
});
world.constraints.forEach(constraint => {
serializedWorld.constraints.push({
type: constraint.type,
bodyA: constraint.bodyA.name,
bodyB: constraint.bodyB.name,
anchorA: [constraint.anchorA.x, constraint.anchorA.y, constraint.anchorA.z],
anchorB: [constraint.anchorB.x, constraint.anchorB.y, constraint.anchorB.z],
// дополнительные параметры конкретного типа
});
});
const jsonString = JSON.stringify(serializedWorld);
Особенности:
name или
id).gravity,
timestep) обеспечивают одинаковое поведение при
восстановлении.Процесс восстановления требует создания нового мира и последовательного добавления тел и ограничений. Пример:
const parsed = JSON.parse(jsonString);
const newWorld = new OIMO.World();
newWorld.gravity = new OIMO.Vec3(...parsed.settings.gravity);
newWorld.timeStep = parsed.settings.timestep;
const bodyMap = {};
parsed.bodies.forEach(b => {
const body = new OIMO.RigidBody({
type: b.type,
position: new OIMO.Vec3(...b.position),
rotation: new OIMO.Quat(...b.rotation)
});
b.shapes.forEach(s => {
body.addShape(new OIMO.Shape({
type: s.type,
size: s.size,
friction: s.friction,
restitution: s.restitution
}));
});
body.linearVelocity = new OIMO.Vec3(...b.linearVelocity);
body.angularVelocity = new OIMO.Vec3(...b.angularVelocity);
newWorld.addRigidBody(body);
bodyMap[b.name] = body;
});
parsed.constraints.forEach(c => {
const constraint = new OIMO.Constraint({
type: c.type,
bodyA: bodyMap[c.bodyA],
bodyB: bodyMap[c.bodyB],
anchorA: new OIMO.Vec3(...c.anchorA),
anchorB: new OIMO.Vec3(...c.anchorB)
});
newWorld.addConstraint(constraint);
});
Ключевые моменты:
bodyMap обеспечивает правильную привязку
ограничений к телам.dynamic — полностью
физически активное, static — неподвижное,
kinematic — управляемое программно. При сериализации важно
сохранять тип, иначе восстановление нарушит логику взаимодействия.Сериализация и десериализация в Oimo.js позволяют создавать сложные физические сцены с возможностью сохранения и восстановления их точного состояния, что является критически важным для игр, симуляций и научных приложений.