Методы моделирования анимации в трехмерном пространстве: углубленный анализ метода ключевых кадров для академической работы

В сфере современных цифровых технологий 3D-анимация занимает одно из центральных мест, преобразуя наше восприятие визуального контента от киноиндустрии и видеоигр до инженерного проектирования и виртуальной реальности. Она позволяет вдохнуть жизнь в статические объекты, создавая динамичные и убедительные виртуальные миры. Среди множества техник создания движения, метод ключевых кадров (key-framing) выступает как один из наиболее фундаментальных и широко используемых подходов, служащий краеугольным камнем для большей части профессиональной анимации.

Настоящая академическая работа ставит своей целью не просто описание, а глубокий теоретический и практический анализ метода ключевых кадров. Мы рассмотрим его исторические корни, детально изучим математические модели и алгоритмы интерполяции, которые лежат в основе плавного движения, проведем сравнительный анализ с альтернативными методами анимации и исследуем архитектурные решения для его программной реализации, сфокусировавшись на C# и OpenGL. Такая структура позволит не только всесторонне осмыслить суть метода, но и подготовит почву для потенциального раздела по практической реализации, предоставляя студенту технического или IT-направления все необходимые знания для создания собственной анимационной системы, что является весомым дополнением к теоретическим изысканиям.

Теоретические основы метода ключевых кадров в 3D-анимации

Метод ключевых кадров является одним из столпов современной 3D-анимации, позволяющим художникам и разработчикам определять ключевые моменты движения, а машине — заполнять промежутки, создавая иллюзию непрерывного потока. Этот подход лежит в основе создания динамических сцен в самых разных областях, от голливудских блокбастеров до интерактивных игровых миров, что подтверждает его универсальность и значимость в индустрии.

Определение и базовые принципы ключевых кадров

В самом сердце метода ключевых кадров лежит идея, что нет необходимости описывать каждый отдельный кадр анимации. Вместо этого, аниматор задает ключевые кадры (keyframes) — это конкретные моменты времени, в которых объект имеет определенное состояние. Под состоянием объекта понимается совокупность его свойств: позиция (местоположение в 3D-пространстве), ориентация (поворот вокруг своих осей), масштаб (размер), а также другие атрибуты, такие как цвет, прозрачность, форма или даже параметры деформации.

Представьте, что вы анимируете летящую птицу. Вы можете задать ключевой кадр, когда птица только взлетает, второй — когда она достигает высшей точки полета, и третий — когда она приземляется. Между этими ключевыми кадрами программное обеспечение самостоятельно вычисляет все промежуточные состояния объекта. Этот автоматизированный процесс называется интерполяцией или твинингом (от англ. «in-betweening»). Интерполяция заполняет «пробелы» между заданными аниматором точками, создавая плавный, последовательный переход от одного ключевого кадра к другому. Таким образом, ключевые кадры выступают в роли «якорей», фиксирующих критические положения и свойства, которые определяют общую логику и характер движения или трансформации. Важно отметить, что такой подход существенно сокращает время производства, позволяя аниматорам сосредоточиться на художественном аспекте, а не на рутинном прорисовывании каждого кадра.

Исторический контекст и эволюция метода

Концепция ключевых кадров уходит корнями глубоко в историю анимации, задолго до появления компьютеров. Еще в XIX веке изобретатели, такие как Уильям Горнер с его зоотропом (1834) и Эмиль Рейно с праксиноскопом (1877), использовали принцип последовательности статических изображений, которые, быстро сменяя друг друга, создавали иллюзию движения.

В традиционной, рисованной анимации, роль «ключевых кадров» выполняли рисунки, созданные главными художниками-аниматорами, называемыми фазовщиками. Эти рисунки, известные как «ключевые фазы», определяли начало, середину и конец основного действия. Затем менее опытные художники, «ин-битвинеры», заполняли промежуточные кадры, обеспечивая плавность перехода. Этот трудоемкий процесс был особенно развит в студиях, таких как Disney, которая в 1937 году, при создании «Белоснежки и семи гномов», внедрила многослойную камеру. Это изобретение позволяло создавать эффект глубины и перспективы, а также эффективно управлять сложными сценами, где движение каждого элемента требовало тщательного планирования ключевых фаз.

С появлением компьютеров в середине XX века и развитием компьютерной графики в 1970-х и 1980-х годах, процесс «фазовки» был автоматизирован. Вместо ручного дорисовывания промежуточных фаз, алгоритмы начали вычислять их на основе математических моделей. Это значительно ускорило и упростило создание сложной анимации, открыв путь для современных 3D-анимационных фильмов, видеоигр и визуальных эффектов. Таким образом, компьютерная анимация унаследовала и усовершенствовала принцип ключевых кадров, сделав его краеугольным камнем своей методологии, что позволило достичь невиданных ранее масштабов и детализации в визуальных проектах.

Трансформации объектов в 3D-пространстве

В основе любой 3D-анимации лежит изменение состояния объектов в трехмерном пространстве. Эти изменения называются трансформациями и включают три основных типа:

  1. Перемещение (Translation): Изменение позиции объекта в пространстве. Объект смещается вдоль осей X, Y и Z.
  2. Вращение (Rotation): Изменение ориентации объекта. Объект поворачивается вокруг одной или нескольких осей. Вращение может быть представлено углами Эйлера, кватернионами или матрицами вращения.
  3. Масштабирование (Scaling): Изменение размера объекта. Объект может быть увеличен или уменьшен равномерно по всем осям или асимметрично.

Математически эти трансформации часто описываются с помощью матриц трансформации (или аффинных матриц). Это квадратные матрицы, обычно 4×4, которые позволяют объединить несколько преобразований (перемещение, вращение, масштабирование) в одну операцию. Применение матрицы трансформации к вектору позиции точки объекта позволяет вычислить ее новое положение в пространстве.

Например, точка с координатами (x, y, z) в гомогенных координатах представляется как вектор-столбец [x, y, z, 1]T. Умножение этого вектора на матрицу трансформации M дает новый вектор [x’, y’, z’, 1]T, представляющий трансформированную точку:

| x' | | m11 m12 m13 m14 | | x |

| y' | = | m21 m22 m23 m24 | × | y |

| z' | | m31 m32 m33 m34 | | z |

| 1 | | m41 m42 m43 m44 | | 1 |

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

Методы интерполяции между ключевыми кадрами: математические модели и алгоритмы

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

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

Линейная интерполяция — это самый простой и интуитивно понятный метод интерполяции. Он предполагает, что значение свойства объекта изменяется с постоянной скоростью между двумя ключевыми кадрами.

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

Математическая формула:
Для двух ключевых кадров, заданных в моменты времени t0 и t1, со значениями свойств P0 и P1 соответственно, значение свойства P(t) в произвольный момент времени t (где t0 ≤ t ≤ t1) можно вычислить по формуле:

P(t) = P0 + (P1 - P0) × (t - t0) / (t1 - t0)

Или, если ввести параметр t ∈ [0, 1] (нормализованное время):

t = (t - t0) / (t1 - t0)

тогда

P(t) = P0 × (1 - t) + P1 × t

Алгоритм:

  1. Определить начальный ключевой кадр (P0, t0) и конечный ключевой кадр (P1, t1).
  2. Для каждого кадра между t0 и t1, вычислить нормализованное время t.
  3. Применить формулу линейной интерполяции для вычисления P(t).

Преимущества:

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

Недостатки:

  • Неестественность движения: В реальном мире объекты редко движутся с идеально постоянной скоростью. Линейная интерполяция может создавать «роботизированные» или механические движения, без ускорений и замедлений.
  • Резкие изменения направления: При изменении траектории движения могут возникать угловатые переходы, что снижает визуальное качество анимации.

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

Дискретная интерполяция, также известная как «константная» или «шаговая» интерполяция, является полной противоположностью плавным методам. В этом случае значение свойства объекта не изменяется между ключевыми кадрами. Вместо этого, оно остается постоянным до момента достижения следующего ключевого кадра, после чего мгновенно принимает новое значение.

Принцип:
Значение P(t) в любой момент времени t между t0 и t1 будет равно значению P0. Только при достижении или превышении t1 значение мгновенно переключится на P1.

Применение:

  • Создание резких, скачкообразных переходов.
  • Изменение дискретных свойств, таких как видимость объекта (появление/исчезновение), смена текстуры, активация или деактивация эффекта.
  • Имитация стоп-моушн анимации.
  • Для анимации, где мгновенное изменение является желаемым эффектом, например, переключение цвета светофора.

Преимущества:

  • Максимальная простота: Нет необходимости в сложных вычислениях.
  • Четкие переключения: Позволяет создавать мгновенные изменения состояния.

Недостатки:

  • Отсутствие плавности: Неприменима для создания естественного или реалистичного движения.

Сплайновая интерполяция (кривые Безье, B-сплайны)

Для создания более плавных, естественных и выразительных движений в 3D-анимации широко используются сплайновые методы интерполяции. Они позволяют управлять не только конечными точками, но и «формой» кривой, по которой движется объект, имитируя ускорение и замедление. Наиболее популярными из них являются кривые Безье и B-сплайны.

Кривые Безье

Кривые Безье — это параметрические кривые, которые определяются набором управляющих точек (контрольных точек). Эти точки не обязательно лежат на самой кривой, но определяют ее форму, «притягивая» к себе кривую.

Принцип:
Кривая Безье степени n определяется (n+1) управляющей точкой P0, P1, …, Pn.
Наиболее часто используются кубические кривые Безье (n=3), которые определяются четырьмя управляющими точками: P0 (начальная точка), P1 (первая касательная точка), P2 (вторая касательная точка) и P3 (конечная точка).

Математическая формула (для кубической кривой Безье):

P(t) = (1 - t)3P0 + 3(1 - t)2tP1 + 3(1 - t)t2P2 + t3P3, где t ∈ [0, 1].

Здесь:

  • P(t) — точка на кривой в момент времени t.
  • P0, P1, P2, P3 — управляющие точки.
  • t — параметр, изменяющийся от 0 до 1, представляющий собой нормализованное время.

Алгоритм:

  1. Определить начальный и конечный ключевые кадры как P0 и P3 соответственно.
  2. Определить две касательные точки P1 и P2, которые задают характер изгиба кривой. Эти точки обычно рассчитываются на основе «векторов касательных» (tangent handles) в анимационных программах.
  3. Для каждого кадра между ключевыми, вычислить нормализованное время t.
  4. Используя формулу, вычислить P(t).

Преимущества:

  • Плавность: Обеспечивают гладкие, непрерывные кривые.
  • Интуитивный контроль: Управляющие точки и касательные позволяют аниматорам тонко настраивать характер движения (ускорение, замедление, изгибы траектории).
  • Локальность: Изменение одной управляющей точки влияет на форму кривой только в ее окрестностях.

B-сплайны

B-сплайны (базисные сплайны) являются более обобщенными и гибкими, чем кривые Безье. Они также определяются управляющими точками, но в отличие от кривых Безье, B-сплайн не обязательно проходит через все управляющие точки (за исключением концевых для некоторых типов B-сплайнов). Ключевое отличие заключается в использовании узлового вектора (knot vector), который определяет, как управляющие точки влияют на форму кривой.

Принцип:
Кривая B-сплайна степени k (например, кубический B-сплайн, где k=3) определяется набором управляющих точек и узловым вектором. Каждый сегмент B-сплайна локально зависит от k+1 управляющих точек.

Математическая модель (обобщенная для B-сплайнов):

P(u) = Σi=0n Ni,k(u) Pi

Здесь:

  • P(u) — точка на B-сплайне.
  • Pi — i-я управляющая точка.
  • Ni,k(u) — i-я базисная функция B-сплайна k-го порядка, определяемая рекурсивно с использованием узлового вектора.
  • u — параметр узлового вектора.

Преимущества:

  • Высокая гибкость: Позволяют создавать более сложные и гладкие кривые по сравнению с Безье, особенно при большом количестве ключевых кадров.
  • Локальный контроль: Изменение одной управляющей точки влияет только на небольшой участок кривой.
  • Непрерывность: Легко достигается непрерывность разных порядков (C0, C1, C2 и выше), что обеспечивает еще большую гладкость.

Пример псевдокода для линейной интерполяции (C#):

// Структура для представления состояния объекта в ключевом кадре
public struct KeyframeData
{
    public float Time;      // Время в секундах
    public Vector3 Position; // Положение объекта
    public Quaternion Rotation; // Вращение объекта (кватернион)
    public Vector3 Scale;   // Масштаб объекта
}

public static KeyframeData LerpKeyframes(KeyframeData kf1, KeyframeData kf2, float currentTime)
{
    KeyframeData result = new KeyframeData();

    // Вычисление нормализованного параметра t
    float t = (currentTime - kf1.Time) / (kf2.Time - kf1.Time);
    t = Mathf.Clamp01(t); // Ограничиваем t в диапазоне [0, 1]

    // Линейная интерполяция позиции
    result.Position = Vector3.Lerp(kf1.Position, kf2.Position, t);

    // Линейная интерполяция вращения (Spherical Linear Interpolation - Slerp для кватернионов)
    result.Rotation = Quaternion.Slerp(kf1.Rotation, kf2.Rotation, t);

    // Линейная интерполяция масштаба
    result.Scale = Vector3.Lerp(kf1.Scale, kf2.Scale, t);

    return result;
}

Для сплайновой интерполяции, например, кубической кривой Безье, потребуется более сложная функция, которая будет принимать четыре контрольные точки (две ключевые и две касательные) и параметр t.

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

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

Временная интерполяция касается того, как быстро или медленно изменяются значения свойств объекта во времени. Она определяет «тайминг» движения. Например, линейная временная интерполяция означает постоянную скорость изменения свойства, тогда как сплайновая позволяет моделировать ускорение (ease-in) и замедление (ease-out), делая движение более естественным. Это особенно актуально для таких свойств, как скорость изменения цвета, прозрачности или интенсивности света.

Пространственная интерполяция относится к тому, как объект движется в пространстве, то есть по какой траектории. Это особенно важно для свойства «положение» (Position). Линейная пространственная интерполяция заставит объект двигаться по прямой линии между двумя ключевыми точками. Сплайновая пространственная интерполяция, напротив, позволит объекту следовать по криволинейной траектории, создавая более сложные и естественные движения, например, для камеры, персонажа или летящего снаряда.

Программы для 3D-анимации часто позволяют независимо настраивать временную и пространственную интерполяцию. Например, объект может двигаться по изогнутой (сплайновой) траектории, но с постоянной скоростью (линейная временная интерполяция), или же двигаться по прямой траектории, но с ускорением и замедлением. Это даёт аниматорам мощный инструмент для достижения желаемого визуального эффекта.

Редакторы кривых (F-кривые/Graph Editor)

Современные программы для 3D-анимации предоставляют аниматорам мощный инструмент для контроля над интерполяцией — редакторы кривых, часто называемые F-кривыми (Function Curves) или Graph Editor.

Принцип работы:
В редакторе кривых горизонтальная ось обычно представляет время (например, кадры или секунды), а вертикальная ось — значение анимируемого свойства (например, координата X позиции, угол вращения по Y, значение масштаба по Z, или яркость света). Каждый ключевой кадр отображается как точка на этой кривой.

Например, если вы анимируете перемещение объекта по оси Y, то кривая в редакторе F-кривых будет показывать, как изменяется координата Y объекта с течением времени.

Манипулирование касательными:
Особая мощь F-кривых заключается в возможности манипулирования касательными (тангентами), которые отходят от ключевых точек на кривой. Эти касательные напрямую связаны с управляющими точками сплайнов (например, P1 и P2 для кубической кривой Безье). Изменяя наклон и длину касательных, аниматор может:

  • Контролировать ускорение и замедление (Ease-in / Ease-out): Более пологие касательные в начале или конце движения создают эффект плавного старта или остановки.
  • Настраивать траекторию: Изменяя пространственные касательные, можно точно формировать изгибы пути, по которому движется объект.
  • Создавать «отскоки» или «перелеты»: Путем манипуляции касательными можно добиться эффекта, когда объект «перелетает» целевое значение, а затем возвращается к нему, что добавляет анимации живости.

Пример использования F-кривых:
Предположим, объект должен плавно стартовать, быстро набрать скорость, а затем плавно остановиться. В редакторе F-кривых это будет выглядеть как S-образная кривая: сначала пологая, затем крутая, и снова пологая. Это достигается путем изменения касательных в начале и конце движения, делая их более горизонтальными.

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

Сравнительный анализ метода ключевых кадров с другими подходами к 3D-анимации

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

Анимация методом ключевых кадров: преимущества и ограничения

Метод ключевых кадров является де-факто стандартом во многих областях анимации благодаря своей гибкости и контролю.

Преимущества:

  • Полный контроль: Аниматор имеет абсолютный контроль над каждым аспектом движения, таймингом и характером изменений. Это позволяет создавать точные, стилизованные и выразительные движения, которые могут быть невозможны при автоматизированных методах.
  • Предсказуемость: Результат анимации точно соответствует заданным ключевым кадрам и параметрам интерполяции, что упрощает итерационный процесс и отладку.
  • Легкость редактирования: Изменение одного или нескольких ключевых кадров относительно легко, поскольку влияет только на соответствующий сегмент анимации. Аниматор может быстро корректировать тайминг или траекторию.
  • Экономия ресурсов: Для относительно простых движений или коротких циклов анимации ключевые кадры требуют меньше вычислительных ресурсов и объема данных по сравнению с захватом движения или физической симуляцией.
  • Универсальность: Применим для анимации практически любых свойств объекта: положения, вращения, масштаба, цвета, прозрачности, деформации меша, параметров материалов и эффектов.

Ограничения:

  • Трудоемкость для сложных движений: Создание очень реалистичных или сложных движений (например, ходьбы или бега персонажа с сотнями суставов) исключительно вручную методом ключевых кадров может быть чрезвычайно трудоемким и требовать высокого уровня мастерства.
  • Неестественность без сложных интерполяций: Использование только линейной интерполяции приводит к механическим, неестественным движениям. Для достижения реализма требуются продвинутые методы сплайновой интерполяции и тонкая настройка F-кривых.
  • Проблема «неоднородности» движения: При ручном создании сложных движений часто возникает проблема отсутствия микроколебаний и мелких деталей, присущих реальному движению, что делает анимацию «слишком чистой» и менее живой.
  • Отсутствие интерактивности: По своей сути, ключевая анимация является «запеченной» последовательностью, не реагирующей на внешние воздействия в реальном времени без дополнительных систем.

Процедурная анимация

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

Принцип:
Примерами процедурной анимации могут служить:

  • Системы частиц: Определяются правила поведения отдельных частиц (гравитация, ветер, столкновения), и система сама генерирует движение тысяч частиц (дым, огонь, взрывы).
  • Фрактальные анимации: Движение генерируется на основе математических фрактальных функций.
  • Имитация толпы: Алгоритмы определяют правила поведения каждого агента в толпе (избегание препятствий, следование за лидером), и система генерирует их движение.
  • Алгоритмы ходьбы: Модель ходьбы может быть сгенерирована процедурно на основе параметров (длина шага, скорость).

Преимущества:

  • Автоматизация и сложность: Позволяет создавать очень сложные и детализированные движения, которые были бы невозможны или крайне трудоемки при ручном ключевом анимировании.
  • Вариативность: Легко генерировать множество уникальных вариантов движения, изменяя исходные параметры алгоритма.
  • Экономия времени: Для повторяющихся или сложных движений, процедурный подход может быть значительно быстрее.
  • Интерактивность: Часто хорошо интегрируется с интерактивными системами, позволяя движению реагировать на ввод пользователя или изменения в среде.

Недостатки:

  • Сложность настройки: Создание и отладка алгоритмов может быть сложной и требовать навыков программирования.
  • Отсутствие прямого контроля: Аниматор теряет прямой контроль над «микродвижениями», что может затруднить достижение конкретного художественного видения.
  • Непредсказуемость: При сложных алгоритмах результат может быть менее предсказуемым.

Сравнение с ключевыми кадрами: Ключевые кадры дают прямой контроль над «что» и «когда», в то время как процедурная анимация фокусируется на «как» и «почему» движения, генерируя его на основе логики. Они часто дополняют друг друга: базовое движение может быть задано ключевыми кадрами, а затем обогащено процедурными эффектами (например, дрожание камеры).

Физическая анимация

Физическая анимация (или физическое моделирование) основана на применении законов физики к виртуальным объектам. Движение генерируется путем симуляции взаимодействия объектов с силами (гравитация, ветер, столкновения, трение) и свойствами материалов (масса, жесткость, упругость).

Принцип:

  • Динамика твердых тел: Симуляция падения, столкновений и отскоков объектов.
  • Динамика мягких тел: Симуляция поведения тканей, жидкостей, волос, дыма, огня.
  • Реакции персонажей: Симуляция ответа персонажа на внешние воздействия (падения, удары).

Преимущества:

  • Реализм: Высочайший уровень реализма, поскольку движение соответствует реальным физическим законам.
  • Автоматизация сложных взаимодействий: Автоматически генерирует сложные взаимодействия между объектами, которые было бы невозможно анимировать вручную.
  • Естественные реакции: Объекты реалистично реагируют на изменения окружающей среды.

Недостатки:

  • Вычислительная сложность: Требует значительных вычислительных мощностей, особенно для симуляции жидкостей, газов или сложных деформаций.
  • Сложность контроля: Трудно предсказать и точно контролировать результат симуляции для достижения конкретного художественного эффекта. Часто требуется множество итераций и «запекание» (baking) симуляции.
  • Не всегда подходит для стилизации: Может быть избыточной или нежелательной для стилизованной анимации, где физика намеренно нарушается.

Сравнение с ключевыми кадрами: Физическая анимация генерирует движение «снизу вверх» из базовых физических принципов, тогда как ключевые кадры — это «сверху вниз», определяемые аниматором. Физическая анимация часто используется для добавления вторичных деталей к ключевой анимации (например, колебание ткани на движущемся персонаже) или для разрушений. Почему бы не использовать преимущества каждого метода для достижения максимального эффекта?

Анимация захватом движения (Motion Capture)

Анимация захватом движения (Motion Capture, MoCap) — это технология записи движений реальных объектов или людей и их последующего переноса на 3D-модели. Актеры надевают специальные костюмы с маркерами, движения которых фиксируются камерами или инерционными датчиками.

Принцип:

  1. Запись: Актер выполняет движения в специальной студии, оборудованной системой захвата движения.
  2. Обработка данных: Полученные данные (позиции маркеров) очищаются от шумов и преобразуются в данные движения для скелета 3D-модели.
  3. Применение к модели: Обработанные данные применяются к управляющему скелету 3D-персонажа.

Преимущества:

  • Высочайший реализм: Позволяет получить максимально естественные и реалистичные движения человека или животного, которые крайне сложно воспроизвести вручную.
  • Экономия времени: Для сложных и длительных последовательностей движения (например, полноценные сцены с диалогами) MoCap значительно быстрее, чем ручная ключевая анимация.
  • Эмоциональная выразительность: Переносит нюансы живого исполнения актера на цифровую модель.

Недостатки:

  • Требования к оборудованию: Требует дорогостоящего оборудования (камеры, костюмы, датчики, программное обеспечение).
  • Сложности редактирования: Редактирование захваченного движения может быть сложным, особенно если нужно изменить детали или переделать часть движения без повторной записи. «Запеченные» данные менее гибки, чем ключевые кадры.
  • Проблемы с «грязными» данными: Данные MoCap часто содержат шумы и артефакты, требующие тщательной очистки и обработки.
  • Не подходит для стилизации: MoCap плохо подходит для стилизованной или мультяшной анимации, где требуется преувеличение и нарушение физических законов.

Сравнение с ключевыми кадрами: MoCap — это «запись реальности», а ключевые кадры — «созидание реальности». Часто используется гибридный подход: основное движение записывается через MoCap, а затем дорабатывается и корректируется с помощью ключевых кадров (keyframe cleanup). Это позволяет сочетать реализм MoCap с художественным контролем ключевой анимации.

Сводная таблица сравнения методов анимации:

Метод Основной принцип Преимущества Недостатки Области применения
Ключевые кадры Ручное задание состояний в ключевых точках, интерполяция между ними Полный контроль, предсказуемость, легкое редактирование Трудоемкость для сложных движений, неестественность без сплайнов Все виды анимации: персонажи, объекты, камеры, интерфейсы, VFX. Базовая техника.
Процедурная анимация Генерация движения по алгоритмам и правилам Автоматизация, сложность, вариативность, интерактивность Сложность настройки, отсутствие прямого контроля Системы частиц, волосы, трава, жидкости, толпы, генеративные эффекты.
Физическая анимация Симуляция движения на основе законов физики Высокий реализм, автоматизация сложных взаимодействий Вычислительная сложность, сложность контроля Разрушения, динамика тканей, волос, жидкостей, твердых/мягких тел, симуляции.
Захват движения (MoCap) Запись движений реальных объектов/актеров Высочайший реализм, экономия времени для сложных движений Дорогое оборудование, сложности редактирования, «грязные» данные Реалистичная анимация персонажей (игры, кино), спортивный анализ.

Реализация 3D-анимации методом ключевых кадров: архитектура и программирование

Практическая реализация 3D-анимации методом ключевых кадров требует понимания как концептуальных основ, так и архитектурных решений, а также владения языками программирования и графическими API. В данном разделе мы рассмотрим типовую архитектуру приложения и приведем примеры реализации интерполяции на C# с использованием базовых принципов OpenGL для визуализации.

Архитектура приложения для 3D-анимации

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

  1. Движок рендеринга (Rendering Engine):
    • Задача: Отвечает за отрисовку 3D-сцены на экране. Он преобразует математические описания объектов (вершины, грани, текстуры) в пиксели, учитывая освещение, камеры и материалы.
    • Компоненты: Графический API (OpenGL, DirectX, Vulkan), шейдеры (для обработки вершин и фрагментов), система управления состоянием рендеринга (blending, depth testing, culling).
    • Взаимодействие с анимацией: Получает от системы анимации обновленные матрицы трансформации или положения вершин для каждого кадра и отрисовывает объекты в их текущем анимированном состоянии.
  2. Система анимации (Animation System):
    • Задача: Хранение данных анимации (ключевые кадры, кривые интерполяции), управление воспроизведением, вычисление промежуточных состояний.
    • Компоненты:
      • Менеджер ключевых кадров: Хранит наборы KeyframeData для различных свойств объекта.
      • Интерполяционный модуль: Реализует алгоритмы интерполяции (линейная, сплайновая, Slerp для вращений).
      • Планировщик анимации: Определяет, какие анимации должны быть воспроизведены в данный момент, управляет их смешиванием (blending) и переходами (transitions).
      • Скелетная анимация (для персонажей): Управляет иерархией костей, их трансформациями и применением скининга к мешу.
    • Взаимодействие: Обновляет состояние объектов (позиция, вращение, масштаб) на основе текущего времени анимации.
  3. Пользовательский интерфейс (User Interface — UI):
    • Задача: Предоставляет инструменты для создания, редактирования и воспроизведения анимации.
    • Компоненты:
      • Таймлайн (Timeline): Визуальное представление ключевых кадров во времени.
      • Редактор F-кривых (Graph Editor): Инструмент для детальной настройки интерполяции.
      • Окно просмотра (Viewport): Отображает 3D-сцену и позволяет манипулировать объектами.
      • Панели свойств: Для изменения параметров объектов и анимаций.
    • Взаимодействие: Принимает ввод пользователя, передает команды системе анимации и рендеринга.
  4. Менеджер ресурсов (Resource Manager):
    • Задача: Загрузка, хранение и управление 3D-моделями (меши, текстуры, материалы), анимационными данными и другими активами.
    • Взаимодействие: Предоставляет системе анимации и рендеринга необходимые данные объектов.

Схема взаимодействия компонентов:


graph TD
    UI --> AnimationSystem
    UI --> RenderingEngine
    AnimationSystem --> RenderingEngine
    AnimationSystem --> ResourceManager
    RenderingEngine --> ResourceManager

Этапы разработки приложения

Разработка приложения для 3D-анимации, использующего ключевые кадры, включает следующие ключевые этапы:

  1. Моделирование и импорт: Создание 3D-моделей (статичных объектов, персонажей) в специализированных программах (Blender, Maya) и их импорт в приложение. Это включает загрузку геометрии (вершин, нормалей, текстурных координат), материалов и, при необходимости, скелета.
  2. Структура данных для анимации: Определение структур данных для хранения ключевых кадров. Каждый ключевой кадр должен содержать время и значения анимируемых свойств (например, Vector3 для позиции, Quaternion для вращения, Vector3 для масштаба).
    public class AnimationTrack
    {
        public string PropertyName; // Например, "Position.X", "Rotation.Y"
        public List<Keyframe> Keyframes; // Список ключевых кадров для этого свойства
    
        public float Evaluate(float currentTime)
        {
            // Здесь будет логика интерполяции
            // (например, поиск двух ближайших ключевых кадров и применение Lerp/Spline)
            return 0.0f; // Заглушка
        }
    }
    
    public class Keyframe
    {
        public float Time;
        public float Value; // Значение свойства
        // Дополнительно: TangentIn, TangentOut для сплайнов
    }
    
  3. Система ключевых кадров и интерполяции: Реализация функций для добавления, удаления и редактирования ключевых кадров. Разработка алгоритмов интерполяции (линейной, сплайновой) для каждого типа анимируемого свойства. Для вращений, представленных кватернионами, используется сферическая линейная интерполяция (Slerp), которая предотвращает проблемы «гиббл-лока» (gimbal lock), присущие углам Эйлера.
  4. Применение анимации к объектам: На каждом кадре рендеринга, система анимации вычисляет текущее состояние объекта на основе времени и примененных анимаций. Эти обновленные значения (позиция, вращение, масштаб) затем применяются к матрицам трансформации объектов, которые передаются в рендеринг.
  5. Рендеринг 3D-сцены: Настройка и использование графического API (например, OpenGL) для отрисовки 3D-объектов. Это включает:
    • Инициализацию OpenGL контекста.
    • Загрузку шейдеров для обработки вершин и фрагментов.
    • Создание буферов вершин (VBO) и индексов (EBO) для 3D-моделей.
    • Настройку камеры (матрицы вида и проекции).
    • Отрисовку каждого объекта с применением его текущей матрицы модели, которая включает результаты анимационных трансформаций.
  6. Пользовательский интерфейс: Разработка элементов UI для управления анимацией: слайдер времени, кнопки воспроизведения/паузы, инструменты для создания и редактирования ключевых кадров, возможно, простой редактор F-кривых.

Практическая реализация интерполяции на C# / OpenGL

Рассмотрим фрагменты кода для реализации интерполяции позиции объекта на C# с использованием базовых концепций OpenGL для визуализации. Предположим, у нас есть класс GameObject с полями Position, Rotation, Scale.

1. Структуры данных для ключевых кадров:
Для простоты, будем анимировать только позицию по оси Y.

using System.Collections.Generic;
using OpenTK.Mathematics; // Для Vector3

// Представляет один ключевой кадр для позиции по Y
public struct KeyframePosition
{
    public float Time; // Время ключевого кадра
    public float Y_Position; // Значение позиции по Y
    // Для сплайнов здесь также могут быть поля для касательных
}

// Класс для управления анимационной дорожкой (track)
public class AnimationYPositionTrack
{
    private List<KeyframePosition> _keyframes = new List<KeyframePosition>();

    public void AddKeyframe(float time, float yPosition)
    {
        _keyframes.Add(new KeyframePosition { Time = time, Y_Position = yPosition });
        _keyframes.Sort((a, b) => a.Time.CompareTo(b.Time)); // Сортировка по времени
    }

    public float GetAnimatedYPosition(float currentTime)
    {
        if (_keyframes.Count == 0) return 0.0f;
        if (_keyframes.Count == 1) return _keyframes[0].Y_Position;

        // Найти два ближайших ключевых кадра
        KeyframePosition kf1 = _keyframes[0];
        KeyframePosition kf2 = _keyframes[_keyframes.Count - 1];

        // Ищем интервал
        for (int i = 0; i < _keyframes.Count - 1; i++)
        {
            if (currentTime >= _keyframes[i].Time && currentTime <= _keyframes[i+1].Time)
            {
                kf1 = _keyframes[i];
                kf2 = _keyframes[i+1];
                break;
            }
            else if (currentTime < _keyframes[0].Time) // До первого кадра
            {
                return _keyframes[0].Y_Position;
            }
            else if (currentTime > _keyframes[_keyframes.Count - 1].Time) // После последнего кадра
            {
                return _keyframes[_keyframes.Count - 1].Y_Position;
            }
        }

        // --- Линейная интерполяция ---
        float t = (currentTime - kf1.Time) / (kf2.Time - kf1.Time);
        return kf1.Y_Position * (1 - t) + kf2.Y_Position * t;

        // --- Сплайновая интерполяция (псевдокод для кубического Безье) ---
        // Для кубического Безье нам нужно 4 ключевых кадра
        // P(t) = (1-t)⁴P₀ + 3(1-t)²tP₁ + 3(1-t)t²P₂ + t³P₃
        // В реальной реализации P0 и P3 будут значениями Y, а P1 и P2 - касательными.
        // Это потребует более сложной структуры KeyframePosition, включающей касательные,
        // и более сложной логики поиска 4 контрольных точек для каждого сегмента.
    }
}

2. Интеграция с 3D-объектом и рендерингом (OpenTK/OpenGL):

using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics;

public class AnimatedGameObject
{
    public Vector3 Position = Vector3.Zero;
    public Vector3 Scale = Vector3.One;
    public Quaternion Rotation = Quaternion.Identity;

    public AnimationYPositionTrack YAnimationTrack; // Наша дорожка анимации по Y

    private Matrix4 _modelMatrix; // Матрица модели объекта

    // Конструктор
    public AnimatedGameObject()
    {
        YAnimationTrack = new AnimationYPositionTrack();
    }

    public void Update(float deltaTime, float animationTime)
    {
        // Получаем анимированную позицию Y из трека
        Position.Y = YAnimationTrack.GetAnimatedYPosition(animationTime);

        // Обновляем матрицу модели
        _modelMatrix = Matrix4.Identity;
        _modelMatrix *= Matrix4.CreateScale(Scale);
        _modelMatrix *= Matrix4.CreateFromQuaternion(Rotation);
        _modelMatrix *= Matrix4.CreateTranslation(Position);
    }

    public void Render(Shader shader)
    {
        shader.SetMatrix4("model", _modelMatrix);
        // Здесь должны быть вызовы OpenGL для отрисовки меша объекта
        // Например: GL.BindVertexArray(VAO); GL.DrawElements(PrimitiveType.Triangles, indexCount, DrawElementsType.UnsignedInt, 0);
    }
}

// Пример использования в главном цикле (GameWindow в OpenTK)
public class Game
{
    private AnimatedGameObject _animatedCube;
    private float _currentTime = 0.0f;

    public void Load()
    {
        _animatedCube = new AnimatedGameObject();
        _animatedCube.YAnimationTrack.AddKeyframe(0.0f, 0.0f);   // Начало: Y = 0
        _animatedCube.YAnimationTrack.AddKeyframe(2.0f, 5.0f);   // 2 секунды: Y = 5
        _animatedCube.YAnimationTrack.AddKeyframe(4.0f, 0.0f);   // 4 секунды: Y = 0
    }

    public void Update(float deltaTime)
    {
        _currentTime += deltaTime;
        if (_currentTime > 4.0f) _currentTime = 0.0f; // Зацикливание анимации

        _animatedCube.Update(deltaTime, _currentTime);
    }

    public void Render()
    {
        GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
        // ... настройки камеры и шейдера ...
        _animatedCube.Render(myShader);
        // SwapBuffers(); // Для OpenTK GameWindow
    }
}

Этот пример демонстрирует базовый подход к хранению ключевых кадров, вычислению анимированных значений с помощью линейной интерполяции и применению этих значений к матрице модели объекта для рендеринга. Для полноценной реализации сплайновой интерполяции потребуется более сложная логика определения контрольных точек (включая касательные) и применение соответствующих математических формул, но принцип взаимодействия с системой анимации и рендеринга останется аналогичным.

Современные тенденции и оптимизации в ключевой анимации

Метод ключевых кадров, несмотря на свою давнюю историю, продолжает активно развиваться, интегрируясь с новыми технологиями и методами. Современные тенденции направлены на повышение эффективности, реалистичности и удобства работы с ключевой анимацией.

Оптимизация данных ключевых кадров

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

  1. Сжатие данных:
    • Квантование: Уменьшение точности значений анимируемых свойств (например, перевод float в half-float или фиксированную точку) для экономии памяти.
    • Дельта-кодирование: Хранение не абсолютных значений, а разницы между текущим и предыдущим ключевым кадром. Это особенно эффективно, когда изменения между кадрами невелики.
    • RLE (Run-Length Encoding): Если значение свойства остается постоянным на протяжении нескольких кадров, можно хранить только его значение и длительность, вместо дублирования ключевых кадров.
  2. Удаление избыточных ключевых кадров:
    • Фильтрация: Автоматическое определение и удаление ключевых кадров, которые не вносят существенного вклада в форму анимационной кривой, сохраняя при этом приемлемое визуальное качество. Алгоритмы могут анализировать кривизну и удалять точки, которые можно интерполировать с минимальной ошибкой.
    • Адаптивное сэмплирование: Вместо равномерного размещения ключевых кадров, они расставляются плотнее там, где движение более сложное и требует большей детализации, и реже там, где движение простое.
  3. Использование специализированных структур данных:
    • Применение деревьев интервалов или других оптимизированных структур для быстрого поиска нужных ключевых кадров при вычислении интерполяции в реальном времени.
    • Предварительное вычисление (baking) сложных сплайновых кривых в более простые формы или дискретные наборы значений для ускорения процесса выполнения в реальном времени, особенно на мобильных устройствах.

Интеграция с другими методами

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

  1. Ключевые кадры + Процедурная анимация:
    • Базовая анимация + детали: Основное движение персонажа или объекта задается ключевыми кадрами. Затем поверх этого процедурно генерируются мелкие детали: колебание одежды, дрожание камеры, реакция второстепенных элементов.
    • Параметризованная анимация: Ключевые кадры могут управлять параметрами процедурных систем. Например, ключевой кадр может изменять скорость ветра, который затем процедурно влияет на движение листвы или волос.
  2. Ключевые кадры + Физическая анимация:
    • Вторичная анимация: Физические симуляции часто используются для создания «вторичного» движения, которое естественно следует за основным, анимированным ключевыми кадрами. Например, персонаж, анимированный ключевыми кадрами, может иметь динамическую физическую симуляцию волос или ткани, которая реагирует на его движение.
    • Переходы и реакции: Ключевые кадры могут задавать начальные и конечные состояния для физических симуляций, например, для симуляции разрушения объекта или падения персонажа, когда он теряет равновесие.
  3. Ключевые кадры + Машинное обучение (ML/AI):
    • Генерация промежуточных кадров: Модели машинного обучения могут быть обучены для создания реалистичных промежуточных кадров, даже при наличии очень sparse (редких) ключевых кадров, что снижает ручной труд аниматора.
    • Стилизация и перенос стилей: ML может анализировать стили анимации и применять их к новым движениям, сгенерированным ключевыми кадрами.
    • Поведенческая анимация: Системы на основе ML могут реагировать на окружающую среду, генерируя анимированные движения, которые выглядят более естественными и адаптивными, чем чисто ключевая анимация. Например, персонаж может адаптировать свою ходьбу к неровной поверхности, основываясь на данных, полученных с помощью ML.
    • Автоматическое создание ключевых кадров: С помощью ML можно автоматизировать часть процесса создания ключевых кадров, например, путем анализа видеоматериала или предсказания оптимальных ключевых поз.

Применение в различных индустриях

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

  • Игровая индустрия: Фундаментален для анимации персонажей, объектов, интерфейсов, кат-сцен. Несмотря на распространение MoCap, ключевые кадры остаются основным инструментом для создания стилизованных движений, анимации лица (facial animation), тонкой настройки MoCap-данных и создания игровых механик, требующих высокой степени контроля.
  • Кино и анимация: Основа для создания как классических мультфильмов, так и современной 3D-анимации. Ключевые кадры используются для всех видов движений: от сложных эмоций персонажей до движений камеры и визуальных эффектов (VFX). Они позволяют режиссерам и аниматорам точно воплощать художественное видение.
  • Архитектурная визуализация: Применяется для создания анимированных пролетов камер по интерьерам и экстерьерам зданий, демонстрации открывающихся дверей или движущихся элементов конструкции.
  • VR/AR (Виртуальная и Дополненная реальность): Используется для анимации интерактивных элементов, персонажей и объектов в виртуальных мирах, а также для создания пользовательских интерфейсов. Гибкость ключевой анимации позволяет адаптировать движения к специфике VR/AR.
  • Инженерное моделирование и проектирование: Применяется для визуализации работы механизмов, симуляции движения деталей машин, демонстрации последовательности сборки или разборки сложных конструкций.

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

Заключение

В ходе данной работы мы совершили глубокое погружение в мир 3D-анимации, сосредоточившись на методе ключевых кадров — технике, которая на протяжении десятилетий остается одним из наиболее фундаментальных и востребованных инструментов в арсенале аниматора. Мы проследили его эволюцию от истоков традиционной анимации до современных компьютерных реализаций, подчеркнув, как автоматизация процесса «фазовки» трансформировала создание движения.

Мы детально проанализировали теоретические основы метода, определив ключевой кадр как якорь, фиксирующий состояние объекта в пространстве и времени, и интерполяцию как процесс, который преобразует эти дискретные состояния в плавное, непрерывное движение. Особое внимание было уделено математическим моделям и алгоритмам интерполяции: от простоты линейной интерполяции до сложности и выразительности сплайновых кривых Безье и B-сплайнов. Была показана решающая роль редакторов кривых (F-кривых) в предоставлении аниматорам тонкого контроля над таймингом и траекторией движения, что позволяет добиваться максимальной естественности и художественной выразительности.

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

Наконец, мы рассмотрели архитектуру типового приложения для 3D-анимации и представили практические фрагменты кода на C# с использованием базовых принципов OpenGL. Это продемонстрировало, как теоретические концепции трансформируются в конкретные программные решения, а также выделило ключевые этапы разработки такой системы. Обзор современных тенденций показал, что ключевая анимация продолжает развиваться, интегрируясь с методами оптимизации данных и передовыми технологиями, такими как машинное обучение.

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

Список использованной литературы

  1. Язык программирования C#. Классика Computers Science. 4-е изд. А. Хейлсберг, М. Торгерсен, С. Вилтамут, П. Голд.
  2. Изучаем C#. 3-е изд. Э. Стиллмен, Дж. Грин.
  3. Алгоритмы: построение и анализ. Чарльз Эрик Лейзерсон, Томас Кормен, Клиффорд Штайн, Рональд Линн Ривест.
  4. Жарков, В.А. Компьютерная графика, мультимедиа и игры на Visual C#. 2005.
  5. Хилл, Ф. OpenGL. Программирование компьютерной графики.
  6. Keyframing animation | What is keyframing — Adobe. URL: https://www.adobe.com/creativecloud/animation/what-is-keyframing.html (дата обращения: 31.10.2025).
  7. What is a Keyframe Animation? Complete Guide to 2D & 3D Animation | LTX Studio. URL: https://www.ltx.studio/keyframe-animation (дата обращения: 31.10.2025).
  8. 3D Animation: Keyframing. URL: https://www.cs.umd.edu/class/fall2000/cmsc427/slides/keyframing.pdf (дата обращения: 31.10.2025).
  9. 12 принципов анимации — Википедия. URL: https://ru.wikipedia.org/wiki/12_%D0%BF%D1%80%D0%B8%D0%BD%D1%86%D0%B8%D0%BF%D0%BE%D0%B2_%D0%B0%D0%BD%D0%B8%D0%BC%D0%B0%D1%86%D0%B8%D0%B8 (дата обращения: 31.10.2025).
  10. Создание анимации трансформеров в Blender — ActionAnimation — Render.ru. URL: https://render.ru/ru/actionanimation/post/23122 (дата обращения: 31.10.2025).
  11. Глава 7. — Ключевые кадры — NETLIB. URL: https://www.netlib.org/cgi-bin/lwg?chapter=7 (дата обращения: 31.10.2025).
  12. Keyframes (ключевые кадры) — что это такое: правила в CSS — Медиа Contented. URL: https://contented.agency/media/keyframes-chto-eto-takoe/ (дата обращения: 31.10.2025).
  13. Использование кадров и ключевых кадров в Animate — Adobe Help Center. URL: https://helpx.adobe.com/ru/animate/using/frames-keyframes.html (дата обращения: 31.10.2025).
  14. Что такое ключевые кадры? — KinoSklad.RU. URL: https://kinosklad.ru/chto-takoe-klyuchevye-kadry/ (дата обращения: 31.10.2025).
  15. Матрица трансформации в 3D графике — Skypro. URL: https://sky.pro/media/matrica-transformacii-v-3d-grafike/ (дата обращения: 31.10.2025).
  16. 3D трансформации. Функции | CSS: Transform (трансформация объектов) — Хекслет. URL: https://ru.hexlet.io/courses/css_transform/lessons/3d-functions/theory_unit (дата обращения: 31.10.2025).
  17. Основы анимации для подвижных 3D моделей — Skypro. URL: https://sky.pro/media/osnovy-animacii-dlya-podvizhnyh-3d-modelej/ (дата обращения: 31.10.2025).
  18. Статья на тему «3D анимация по ключевому кадру» — Инфоурок. URL: https://infourok.ru/statya-na-temu-3d-animaciya-po-klyuchevomu-kadru-6019777.html (дата обращения: 31.10.2025).
  19. Технологии создания и визуализации 3D-анимации — Мир науки. Социология, филология, культурология. URL: https://mir-nauki.com/PDF/17KMN423.pdf (дата обращения: 31.10.2025).
  20. Основы 3d-анимации в cinema 4d для начинающих. URL: https://skillbox.ru/media/design/osnovy-3d-animatsii-v-cinema-4d-dlya-nachinayushchih/ (дата обращения: 31.10.2025).
  21. CSS3 3D-трансформации — html5book. URL: https://html5book.ru/css3-3d-transforms/ (дата обращения: 31.10.2025).

Похожие записи