- •Введение
- •Глава 1. Подготовка к изучению книги
- •Установка DirectX SDK
- •Выбор отладочных или рабочих версий библиотек
- •Настройка вашего компилятора
- •Установка директорий DirectX SDK
- •Привязывание к библиотекам DirectX
- •Установка используемого по умолчанию состояния символа
- •Использование вспомогательного кода книги
- •Использование вспомогательных объектов
- •Проверка вспомогательных функций
- •Двигаясь дальше по книге
- •Глава 2. Синхронизация анимации и движения
- •Использование движения, синхронизированного по времени
- •Считывание времени в Windows
- •Анимирование с использованием временных меток
- •Перемещение, синхронизированное со временем
- •Движение вдоль траекторий
- •Создание анализатора маршрутов .X файла
- •Создание внутриигровых кинематографических последовательностей
- •Посмотрите демонстрационные программы
- •TimedAnim
- •TimedMovement
- •Route
- •Cinematic
- •Глава 3. Использование формата файла .X
- •Работа с .X шаблонами и объектами данных
- •Определение шаблонов
- •Работа со стандартными шаблонами DirectX
- •Открытие .X файла
- •Перечисление объектов данных
- •Получение данных объекта
- •Создание класса .X анализатора
- •Загрузка мешей с использованием D3DX
- •Загрузка мешей, используя анализатор .X
- •Загрузка скелетных мешей
- •Загрузка анимации из .X
- •Загрузка специализированных данных из .X
- •Посмотрите демонстрационные программы
- •ParseFrame
- •Глава 4. Работа со скелетной анимацией
- •Начало скелетной анимации
- •Использование структур скелетов и иерархий костей
- •Использование скелетной структуры и скелетного меша
- •Загрузка иерархий из .X
- •Изменение положения костей
- •Обновление иерархии
- •Работа со скелетными мешами
- •Загрузка скелетных мешей из .X
- •Создание контейнера вторичного меша
- •Сопоставление костей фреймам
- •Обновление скелетного меша
- •Визуализация скелетных мешей
- •Глава 5. Использование скелетной анимации, основанной на ключевых кадрах
- •Использование наборов скелетных анимаций, основанных на ключевых кадрах
- •Использование ключей при анимации
- •Работа с четырьмя типами ключей
- •Считывание данных анимации из .X файлов
- •Прикрепление анимации к костям
- •Обновление анимации
- •Посмотрите демонстрационные программы
- •Глава 6. Комбинирование скелетных анимаций
- •Комбинирование скелетных анимаций
- •Соединение преобразований
- •Улучшение объектов скелетной анимации
- •Посмотрите демонстрационные программы
- •Глава 7. Создание кукольной анимации
- •Работа с физикой твердого тела
- •Создание твердого тела
- •Расположение и ориентирование твердых тел
- •Обработка движения твердых тел
- •Использование сил для создания движения
- •Соединение твердых тел с помощью пружин
- •Обеспечение обнаружения столкновений и ответной реакции
- •Создание систем кукольной анимации
- •Определение состояния твердого тела
- •Хранение костей
- •Создание класса управления куклой
- •Создание данных костей
- •Вычисление ограничивающего параллелепипеда кости
- •Установка сил
- •Объединение костей
- •Обработка столкновений
- •Восстановление соединений костей
- •Перестроение иерархии
- •Посмотрите демонстрационные программы
- •Глава 8. Работа с морфирующей анимацией
- •Морфинг в действии
- •Определение исходного и целевого меша
- •Морфинг мешей
- •Создание морфированного меша при помощи обработки
- •Визуализация морфированных мешей
- •Расчленение наборов
- •Создание морфирующего вершинного шейдера
- •Посмотрите демонстрационные программы
- •Глава 9. Использование морфирующей анимации, основанной на ключевых кадрах
- •Использование наборов морфируемой анимации
- •Создание шаблонов .X для морфируемой анимации
- •Загрузка данных морфируемой анимации
- •Визуализации морфированного меша
- •Получение данных морфируемого меша из альтернативных источников
- •Посмотрите демонстрационные программы
- •Глава 10. Комбинирование морфированных анимаций
- •Комбинирование морфированных анимаций
- •Использование базового меша в комбинированных морфированных анимациях
- •Вычисление разностей
- •Комбинирование разностей
- •Создание вершинных шейдеров комбинированного морфирования
- •Использование вершинного шейдера морфируемого комбинирования
- •Посмотрите демонстрационные программы
- •Глава 11. Морфируемая лицевая анимация
- •Основы лицевой анимации
- •Использование комбинированного морфирования
- •Использования фонем для речи
- •Создание лицевых мешей
- •Создание базового меша
- •Создание выражений лица
- •Создание мешей визем
- •Создание анимационных последовательностей
- •Создание последовательностей фонем
- •Использование анализатора файлов .X для последовательностей
- •Проигрывание лицевых последовательностей со звуком
- •Использование DirectShow для звука
- •Синхронизация анимации со звуком
- •Зацикливание воспроизведения звуков
- •Посмотрите демонстрационные программы
- •Глава 12. Использование частиц в анимации
- •Работа с частицами
- •Основы
- •Рисование частиц с помощью квадратных полигонов
- •Работа с точечными спрайтами
- •Улучшения визуализации частиц при помощи вершинных шейдеров
- •Оживление частиц
- •Передвижение частиц при помощи скорости
- •Использование интеллекта при обработке
- •Создание и уничтожение частиц
- •Управление частицами с помощью класса
- •Использование излучателей в проектах
- •Создание движков частиц в вершинных шейдерах
- •Посмотрите демонстрационные программы
- •Глава 13. Имитирование одежды и анимация мешей мягких тел
- •Имитация одежды в ваших проектах
- •Получение данных одежды из мешей
- •Приложение сил для создания движения
- •Воссоздание и визуализация меша одежды
- •Восстановление исходного меша
- •Добавление дополнительных пружин
- •Загрузка данных масс и пружин из .X файла
- •Создание анализатора .X данных одежды
- •Работа с обнаружением столкновений и реакцией на них
- •Определение объектов столкновений
- •Обнаружение и реакция на столкновения
- •Создание класса меша одежды
- •Использование мешей мягких тел
- •Восстановление мешей мягких тел
- •Посмотрите демонстрационные программы
- •Глава 14. Использование анимированных текстур
- •Использование анимации текстур в ваших проектах
- •Работа с преобразованиями текстур
- •Создание преобразования текстур
- •Установка матриц преобразования текстуры
- •Использование преобразования текстур в проектах
- •Использование файлов видео в качестве текстур
- •Импорт видео при помощи DirectShow
- •Создание специализированного фильтра
- •Работа со специализированным фильтром
- •Создание менеджера анимированных текстур
- •Окончание современной анимации
- •Веб-сайты
- •Рекомендуемые книги
- •DirectX 9.0 SDK
- •GoldWave Demo
- •Paint Shop Pro Trial Version
- •TrueSpace Demo
- •Microsoft Agent and LISET
- •Предметный указатель
Созданиекукольнойанимации
Я вычисляю ориентацию, учитывая скорость, основанную на времени. Помните, что скорость была посчитана из момента, а он в свою очередь из вращательного момента. Вращательный момент содержал ось вращения, совсем как кватернион. Обычно вы просто перемножаете скорость и кватернион, после чего разделяете результат на такие части:
q1 = 1|2 vt q
Наконец, после приложения силы к твердому телу вы можете вычислить угол
иось вращения. Теперь вы знаете достаточно, чтобы двигать и вращать твердые тела! Хорошо, я признаю, что немного быстро и в вольном стиле излагал материал
вданном разделе. Но у меня были веские причины - я не хотел загружать вас множеством формул и вычислений. Раздел физики твердого тела существует уже давно,
ипо нему написано множество литературы. Я думаю, что немногие используют физику твердого тела из-за сложности ее математики. Я хочу, чтобы любой мог понять основы динамики твердого тела, не углубляясь в математику. По этой причине я пропустил большинство формул, которые могли бы пригодиться знающим читателям. Как я уже замечал, этот раздел существует долгое время, за которое было написано несколько замечательных книг и статей о нем. Особенно полезен набор статей Chris Hecker'a Behind the Screen series on physics. Вы можете найти эти статьи на домашней странице Chris'a, http://www.d6.com/users/checker.
Теперь идет самая забавная часть - создание набора сил, действующих на твердое тело и заставляющих его двигаться.
Использование сил для создания движения
Теперь вы имеете возможность следить за движением и вращением твердого тела. Они появляются, когда сторонние силы начинают действовать на тело. Для упрощения будем полагать, что возможны только такие силы: приложенная к телу, сопротивление воздуха, тяжести и пружина.
Приложенная сила — это такая сила, которая действует непосредственно, как, например, сила взрыва, толкание персонажем объекта или любой другой тип силы, не относящийся к перечисленным ранее. Как вы можете представить, сила тяжести притягивает объект вниз (или вверх, если захотите), в то время как сопротивление воздуха замедляет движение твердого тела. Пружинная сила (сила сжатия пружины) используется для присоединения твердых тел друг к другу или какой-нибудь точке трехмерного мира.
206 |
Глава 7 |
Как я замечал в последних двух разделах, для хранения сил используются векторы. Каждая сила определяется направлением приложения силы и величиной прилагаемой силы. Величина силы хранится в виде ускорения (в метрах в секунду3 для объекта массой 1). Для углового вращения это значение измеряется в радианах в секунду. Длина вектора силы определяет величину силы. Так, например, для силы тяжести, которая ускоряет объект приблизительно на 9.8 м/с2 в отрицательном направлении оси у (вниз), принимая во внимание массу, вы можете создать вектор:
D3DXVECTOR3 vecGravity = D3DXVECTOR3(0.0f, -9.8f, 0.0) * Mass;
Акак насчет приложенной силы, ускоряющей тело (массой 1) на 10 метров
всекунду в положительном направлении оси х?
D3DXVECTOR3 vecApplied = D3DXVECTOR3(10.0f, 0.0f, 0.0f);
А как же вычисляется сопротивление воздуха? Вы определяете сопротивление воздуха не как остальные силы; вместо этого, она создается из другой силы. Я имею ввиду, что сопротивление воздуха противодействующая сила, которая вычисляется умножением скорости тела на небольшое число (отрицательное число, если быть точным). Для моделирования сопротивления воздуха в вашей системе твердых тел вы можете создать два вектора, представляющие собой противодействующие силы. Эти силы используются для замедления движения, вызванного линейной скоростью и угловым моментом.
Положив, что скорость вашего твердого тела хранится в векторе vecVelocity, а угловой момент в vecMomentum, вы можете создать два вектора (силы и момента) для дальнейшего использования.
D3DXVECTOR3 vecLinearDamping = vecVelocity * LinearDamping; D3DXVECTOR3 vecAngularDamping = vecMomentum * AngularDamping;
Вещественные переменные LinearDamping и AngularDamping отрицательны. Чем больше значения этих переменных4, тем большее сопротивление воздуха действует на тело и тем больше оно замедляется. Обычно я использую значения -0.5 и -0.4 для LinearDamping и AngularDamping соответственно.
3. Автор подразумевает, но явно не показывает, что прикладываемая сила определяет ускорение в метрах
всекунду за секунду. - Примеч. науч. ред.
4. Очевидно — больше по модулю. - Примеч. науч. ред.
Созданиекукольнойанимации
После вычисления векторов, которые представляют силы, противодействующие линейному и вращательному движению, вы можете применять их, как делали это ранее. На самом деле вы можете просто добавить векторы vecLinearDamping и vecAngularDamping к результирующей силе и суммарному моменту.
Хмм, знаете что? Каким то образом я умудрился пропустить объяснение пружинных сил. Это была не ошибка, просто я хотел отложить их рассмотрение до этого момента, чтобы я мог лучше объяснить их. Пружины соединяют твердые тела между собой, гарантируя, что тела, представляющие собой кости персонажа, соединены между собой в правильных точках.
Соединение твердых тел с помощью пружин
Моделирование движения твердого тела и приложенных к нему сил является простой задачей, если вы понимаете основы. Когда же у вас соединяется множество тел, все усложняется. Каждое изменение ориентации твердого тела может вызвать изменения во множестве других тел. Если соединено множество твердых тел, обработка одного перемещения может вызвать обработку еще множества.
Возвратимся к теме. Эти соединенные между собой твердые тела представляют собой кукольный персонаж. Вы знаете, как все устроено - кости кисти присоединены к руке, кость руки присоединена к .... Ну, вы поняли идею. Твердые тела соединяются между собой так же, как и кости в скелетном меше присоединяются к родительским костям (конечно, за исключением корневой кости).
В то время как скелетная структура соединяет кости, используя иерархию фреймов, твердые тела не могут позволить себе такой роскоши; тела полностью свободны и при моделировании перемещаются по всему миру. Необходимо что-то, что держало бы их вместе, и этим чем-то являются пружины.
Как вы можете видеть на рис. 7.9, пружины создаются для каждой точки соединения костей в исходной скелетной структуре.
Когда вы начнете перемещать твердые тела, вам будет необходимо вычислить силы, необходимые каждой пружине для сохранения начальной формы структуры тела. Пружины просто создают силы, двигающие каждый объект в заданном направлении. Но в отличие от упомянутых ранее сил, пружинам необходимо соединить тело не немедленно, а за определенный интервал времени. Это можно реализовать, непосредственно изменяя положение и угловой момент каждого тела.
208 |
Глава7 |
Рис. 7.9. Пружины соединяют твердые тела в точках сочленения костей
Сначала о главном, вам необходимо узнать точки соединения костей. Когда вы создаете ограничивающие параллелепипеды, вам необходимо добавить точку, которая определяет место соединения параллелепипеда с параллелепипедом родительской кости. Вам также необходимо добавить точку, представляющую собой смещение от центра родительской кости до точки соединения. Эти две точки показаны на рис. 7.10.
Помните, ранее в этой главе, вы определили восемь векторов, представляющих собой углы твердого тела? Было два набора по восемь вершин, один для определения локальных координат, а другой для определения этих же самых точек в мировых координатах. Теперь вам необходимо добавить еще две точки в список.
Первая точка является смещением от центра кости до точки соединения с родительской костью. Эта точка, имеющая название точка смещения соединения (или просто смещение соединения), представляет собой один конец создаваемой пружины, которая будет соединять твердые тела после их перемещений.
Вторая точка является смещением от центра родительской кости до точки соединения с родительской костью. Эта вторая точка, называемая точка родительского смещения (или просто родительское смещение), использует преобразования родительской кости для ориентирования, противодействуя преобразованию кости (как вы видели ранее). Вторая точка представляет собой другой конец создаваемой пружины для соединения костей.
Созданиекукольнойанимации |
209 |
Точка присоединения кости к родителю
Рис. 7.10. Каждая кость определяется размерами ограничивающего параллелепипеда и точкой соединения с родительской костью.
Т. к. вторая добавляемая точка использует преобразование родительской кости, не обязательно хранить ее в наборе векторов локального пространства; просто храните ее в наборе векторов преобразования. Это дает вам возможность определить два новых набора векторов.
D3DXVECTOR3 vecLocalPoints[9];
D3DXVECTOR3 vecWorldPoints[10] ;
Вы уже видели, как сохранять координаты угловых точек с помощью векторов, так что я пропущу эту часть и покажу вам, как сохранять значения смещения соединения и родительского смещения. Восьмая точка будет представлять координаты смещения соединения, а точка девять — родительского смещения.
Вектор смещения соединения хранится в объекте D3DXVECTOR3, имеющем название vecJointOffset, в то время как вектор родительского смещения хранится в vecParentOffset. Первое, что необходимо сделать, это сохранить вектор смещения соединения в соответствующем векторе локального пространства.
vecLocalPoints[8] = vecJointOffset;
Теперь вы можете преобразовывать девять точек из локального пространства
вмировое, как вы делали это ранее. После чего, точка 8 будет содержать координаты
вмировом пространстве точки присоединения кости к родителю.
210 |
Глава7 |
Что же касается вектора родительского смещения, вам необходимо поместить его в один из векторов vecWorldPoints. Чтобы сделать это, используйте преобразования родительской кости. Если ориентация родителя кости хранится в виде матрицы преобразования matParentOrientation, а положение в векторе vecParentPosition, вы можете вычислить координаты преобразованной точки так:
D3DXVec3TransformCoord(&vecWorldPoints[9], \ &vecParentOffset, \ &matParentOrientation);
vecWorldPoints[9] += vecParentPosition;
После преобразования координат точек в мировое пространство вы можете использовать их для создания пружины, показанной на рис. 7.11.
Рис. 7.11. Вы создаете вектор пружины, соединяя точки смещения соединения и родительского смещения. Обе точки задаются в мировых координатах
//vecPosition = положение тела
//Получить положение смещения соединения в мировых координатах D3DXVECTOR3 vecBonePos = vecWorldPoints[8];
//Получить вектор из точки в центр тела
Создание кукольной анимации |
211 |
//Он используется для вычисления момента D3DXVECTOR3 vecPtoC = vecPosition - vecBonePos;
//Получить положение родительского смещения в мировых координатах D3DXVECTOR3 vecParentPos = vecWorldPoints[9];
//Вычислить вектор пружины из точек соединения и родительской D3DXVECTOR3 vecSpring = vecBonePos - vecParentPos;
Теперь вектор vecSpring содержит разницу координат, которую вы используете для перемещения кости для соединения ее с родителем. По аналогии с реальным человеком, при соединении с родителем двигаются только дочерние кости. (В качестве примера: ваша рука повторяет движение груди.) Таким образом, при движении корневой кости (представляющей грудь персонажа или центр масс) будут двигаться и все присоединенные к ней кости (вместо того, чтобы двигать корневую кость для сохранения соединения с дочерними).
Т. к. вы просто хотите переместить кость для воссоединения с родительской, вы можете просто добавить вектор vecSpring непосредственно к положению вашего тела (игнорируя таким образом константы пружины). Также вы можете вычислить векторное произведение разницы положения точки и положения смещения вращения и пружины для получения углового момента кости, таким образом повернув ее, чтобы убедиться, что существуют точки касания.
vecPosition += vecSpring; D3DXVECTOR3 vecCross;
D3DXVec3Cross(&vecCross, &vecBtoC, &vecSpring); vecAngularMoment += vecCross;
После изменения момента вы можете преобразовать его, используя обратную матрицу тензора инерции кости, и сохранить результат в векторе угловой скорости.
D3DXVECTOR3 vec D3DXVec3TransformCoord(&vecAngularVelocity, \
&vecAngularMomentum, \ &matInvWorldInertiaTensor);
Со всеми этими разговорами о векторах смещения, соединения и родительского смещения я забыл упомянуть, откуда получать их значения. При вычислении размера ограничивающего параллелепипеда вам необходимо принимать во внимание координаты кости и ее родителя в мировом пространстве.