Треки анимации: KeyframeTrack и его подтипы

Анимационная подсистема Three.js основана на идее разделения анимации на независимые каналы данных — треки анимации. Каждый трек описывает изменение одного конкретного свойства объекта во времени.

Треки объединяются в объект AnimationClip, который представляет завершённую анимационную последовательность. Внутри клипа может находиться любое количество треков, управляющих различными параметрами сцены: положением объектов, вращением, масштабом, цветом материалов, морф-таргетами и другими характеристиками.

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


Базовый класс KeyframeTrack

Класс KeyframeTrack описывает анимацию одного свойства объекта через набор ключевых кадров.

Ключевой кадр содержит:

  • момент времени
  • значение анимируемого параметра

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

Основные параметры конструктора:

new THREE.KeyframeTrack(name, times, values, interpolation)

Параметры:

  • name — строка пути к анимируемому свойству
  • times — массив времени ключевых кадров
  • values — массив значений
  • interpolation — тип интерполяции

Пример создания трека положения:

const times = [0, 1, 2];
const values = [
    0, 0, 0,
    5, 0, 0,
    10, 0, 0
];

const track = new THREE.VectorKeyframeTrack(
    '.position',
    times,
    values
);

Здесь:

  • в момент 0 секунд объект находится в (0,0,0)
  • через 1 секунду — в (5,0,0)
  • через 2 секунды — в (10,0,0)

Путь к свойству (Property Binding)

Поле name указывает путь к свойству объекта, которое будет анимироваться.

Структура записи:

nodeName.property

или

.property

Примеры:

.position
.rotation
.scale
.material.opacity
.bones[Arm].rotation
.morphTargetInfluences[0]

Механизм связывания называется PropertyBinding. Он позволяет системе анимации автоматически находить соответствующее свойство в объекте сцены.


Хранение ключевых кадров

Массив времени

Массив times хранит временные точки:

[0, 1, 2, 3]

Каждое число — момент времени в секундах.


Массив значений

Массив values содержит данные, соответствующие каждому времени.

Тип данных зависит от вида трека:

Тип трека Размер значения
Scalar 1
Vector3 3
Quaternion 4
Color 3
Boolean 1
String 1

Пример для Vector3:

values = [
  x1, y1, z1,
  x2, y2, z2,
  x3, y3, z3
]

Интерполяция между кадрами

KeyframeTrack поддерживает несколько типов интерполяции.

Линейная интерполяция

Самый распространённый режим.

THREE.InterpolateLinear

Значения плавно изменяются между ключевыми кадрами.


Дискретная интерполяция

Значение остаётся постоянным до следующего ключевого кадра.

THREE.InterpolateDiscrete

Используется для:

  • переключения состояний
  • булевых значений
  • строк

Кубическая интерполяция

Более плавное изменение значений.

THREE.InterpolateSmooth

Применяется для сложных анимаций движения.


Основные подтипы KeyframeTrack

Three.js содержит несколько специализированных классов треков. Каждый из них оптимизирован под конкретный тип данных.


NumberKeyframeTrack

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

Примеры:

  • прозрачность материала
  • интенсивность света
  • угол вращения

Пример:

const times = [0, 1, 2];
const values = [1, 0.5, 0];

const track = new THREE.NumberKeyframeTrack(
    '.material.opacity',
    times,
    values
);

Анимация делает материал постепенно прозрачным.


VectorKeyframeTrack

Применяется для свойств, представленных векторами.

Наиболее частые случаи:

  • position
  • scale
  • direction

Пример:

const times = [0, 1, 2];

const values = [
    0, 0, 0,
    3, 5, 0,
    6, 5, 2
];

const track = new THREE.VectorKeyframeTrack(
    '.position',
    times,
    values
);

Каждый ключевой кадр содержит координаты Vector3.


QuaternionKeyframeTrack

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

В Three.js вращение часто представляется кватернионами, поскольку они:

  • не имеют проблемы гимбал-лок
  • позволяют плавно интерполировать вращение
  • корректно работают с 3D-поворотами

Пример:

const times = [0, 1];

const values = [
    0, 0, 0, 1,
    0, 0.707, 0, 0.707
];

const track = new THREE.QuaternionKeyframeTrack(
    '.quaternion',
    times,
    values
);

Интерполяция выполняется методом slerp (spherical linear interpolation).


ColorKeyframeTrack

Анимирует цвет.

Пример применения:

  • изменение цвета материала
  • переход освещения
  • визуальные эффекты

Пример:

const times = [0, 1, 2];

const values = [
    1, 0, 0,
    0, 1, 0,
    0, 0, 1
];

const track = new THREE.ColorKeyframeTrack(
    '.material.color',
    times,
    values
);

Цвет меняется:

красный → зелёный → синий

BooleanKeyframeTrack

Используется для логических значений.

Пример:

const times = [0, 2];
const values = [true, false];

const track = new THREE.BooleanKeyframeTrack(
    '.visible',
    times,
    values
);

Интерполяция всегда дискретная.


StringKeyframeTrack

Анимирует строковые значения.

Используется редко, но может применяться для:

  • смены текстур
  • переключения состояний
  • управления пользовательскими параметрами

Пример:

const times = [0, 1];
const values = ["idle", "run"];

const track = new THREE.StringKeyframeTrack(
    '.state',
    times,
    values
);

AnimationClip и треки

Один трек управляет только одним свойством. Для создания полноценной анимации несколько треков объединяются в AnimationClip.

Пример:

const positionTrack = new THREE.VectorKeyframeTrack(
    '.position',
    [0, 1, 2],
    [
        0,0,0,
        5,0,0,
        10,0,0
    ]
);

const rotationTrack = new THREE.QuaternionKeyframeTrack(
    '.quaternion',
    [0, 2],
    [
        0,0,0,1,
        0,0.707,0,0.707
    ]
);

const clip = new THREE.AnimationClip(
    'MoveAndRotate',
    2,
    [positionTrack, rotationTrack]
);

В этом клипе:

  • первый трек управляет позиции
  • второй — вращением

Нормализация данных

Для корректной работы трек должен соответствовать ряду требований:

1. Время должно быть отсортировано

0 < 1 < 2 < 3

2. Количество значений должно соответствовать размерности

Например для Vector3:

values.length = times.length × 3

3. Все значения должны быть одного типа

Смешивание типов недопустимо.


Методы KeyframeTrack

setInterpolation()

Позволяет изменить тип интерполяции.

track.setInterpolation(THREE.InterpolateLinear);

getInterpolation()

Возвращает текущий тип интерполяции.

track.getInterpolation();

optimize()

Удаляет избыточные ключевые кадры.

Например, если два соседних кадра имеют одинаковые значения.

track.optimize();

Это уменьшает объём данных и повышает производительность.


validate()

Проверяет корректность структуры трека.

track.validate();

Проверяются:

  • соответствие размеров массивов
  • сортировка времени
  • корректность типов

clone()

Создаёт копию трека.

const copy = track.clone();

Использование с AnimationMixer

Для воспроизведения треков применяется AnimationMixer.

Пример:

const mixer = new THREE.AnimationMixer(mesh);

const action = mixer.clipAction(clip);

action.play();

В игровом цикле:

mixer.update(delta);

delta — время между кадрами.


Производительность и оптимизация

При создании сложных анимаций количество ключевых кадров может быть очень большим. Для оптимизации используются:

1. Сжатие ключевых кадров

Удаление повторяющихся значений.


2. Минимизация треков

Анимировать только те свойства, которые действительно изменяются.


3. Использование Quaternion вместо Euler

Позволяет избежать ошибок интерполяции вращения.


4. Группировка треков

Один клип может содержать десятки треков, но система анимации эффективно обрабатывает их пакетно.


Типичные области применения

Треки KeyframeTrack используются для:

  • анимации 3D-моделей
  • скелетной анимации
  • морф-таргетов
  • движения камер
  • эффектов материалов
  • анимации света
  • интерактивных сцен

Система треков является фундаментом всей анимационной архитектуры Three.js и обеспечивает универсальный механизм описания изменений свойств объектов во времени.