Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
DirectX. Продвинутая Анимация (2004) [rus].pdf
Скачиваний:
336
Добавлен:
16.08.2013
Размер:
8.39 Mб
Скачать

220

Глава 7

Итак, мой друг, я верю, что вы усвоили все необходимое для создания своей собственной системы кукольной анимации! Я собираюсь быстро показать вам, как применять полученные знания при работе с набором классов, используемых в системах кукольной анимации. Убедитесь, что вы хорошо понимаете все выше изложенное, потому что дальше все пойдет очень быстро!

Создание систем кукольной анимации

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

Но я хочу рассмотреть целую систему кукольной анимации по частям, начав с определения состояние одного твердого тела.

Определение состояния твердого тела

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

class cRagdollBoneState

{

public:

D3DXVECTOR3 m_vecPosition; // Положение D3DXQUATERNION m_quatOrientation; // Ориентация D3DXMATRIX m_matOrientation; // Ориентация

D3DXVECTOR3 m_vecAngularMomentum; // Угловой момент

D3DXVECTOR3 m_vecLinearVelocity; // Линейная скорость

D3DXVECTOR3 m_vecAngularVelocity; // Угловая скорость

//Преобразованные точки, включающие положение присоединения к родителю и смещение от родителя до кости

D3DXVECTOR3 m_vecPoints[10] ;

//Обратная матрица тензора мирового момента инерции D3DXMATRIX m_matInvWorldInertiaTensor;

};

Создание кукольной анимации

221

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

По мере обработки вашей модели состояние костей обновляется в соответствии с действующими силами. Для хранения оставшейся информации о костях, такой как размер, масса и т. д., определим второй класс.

Хранение костей

Оставшиеся данные кости, такие как исходный фрейм кости, размер, масса, коэффициент restitution, сила, момент (просто для перечисления), хранятся в другом классе. Этот класс cRagdollBone определяется так:

class cRagdollBone

{

public:

//Фрейм, к которому присоединена кость D3DXFRAME_EX *m_Frame;

//Размер ограничивающего параллелепипеда D3DXVECTOR3 m_vecSize;

//Масса и 1/массу (единица деленная на массу) float m_Mass;

//Значение коэффициента возврата (restitution)

//0 = нет отскока

//1 = "супер" отскок

//2 = получать энергию при отскоке

float m_Coefficient;

cRagdollBone *m_ParentBone; // указатель на родительскую кость

//смещения присоединения к родителю и родителя к кости D3DXVECTOR3 m_vecJointOffset;

D3DXVECTOR3 m_vecParentOffset;

//Линейная сила и угловой момент

D3DXVECTOR3 m_vecForce;

D3DXVECTOR3 m_vecTorque;

//Начальная ориентация кости D3DXQUATERNION m_quatOrientation;

//Уровень разрешения (0-1) для сферической интерполяции

//Он используется для возвращения костей к начальному

//ориентированию относительно родителя

float m_ResolutionRate;

222

Глава 7

//Обратная матрица тензора момента инерции тела D3DXMATRIX m_matInvInertiaTensor;

//Точки (в локальном пространстве), которые образуют

//ограничивающий параллелепипед и смещение соединения с родителем D3DXVECTOR3 m_vecPoints[9];

//Состояние кости

cRagdollBoneState m_State;

};

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

Кватернион (m_quatOrientation), содержащийся в классе cRagdollBone, представляет собой относительную разность вращений из родительской кости. Он полезен для поддержания формы персонажа при симуляции. Вместо того чтобы определять границы, в которых может вращаться каждая кость по отношению к родителю, вы можете заставить восстанавливаться ориентацию каждой кости к начальной. Я покажу вам, как это делается немного позже; а пока что вернемся к классу cRagdollBone.

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

Создание класса управления куклой

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

class cRagdoll

{

protected:

D3DXFRAME_EX *m_pFrame; // Корневой фрейм иерархии

DWORD m_NumBones; // # костей cRagdollBone *m_Bones; // Список костей

Созданиекукольнойанимации

Пока что класс не выглядит очень пугающе, так к чему суета? Поверьте мне, вы еще не все знаете. Далее идут защищенные функции.

protected:

//Встроенная функция, вычисляющая векторное произведение D3DXVECTOR3 CrossProduct(D3DXVECTOR3 *v1, D3DXVECTOR3 *v2);

//Функция, умножающая вектор на матрицу 3x3 и по желанию

//добавляющая вектор смещения

D3DXVECTOR3 Transform(D3DXVECTOR3 *vecSrc,

D3DXMATRIX *matSrc,

D3DXVECTOR3 *vecTranslate = NULL);

//Получить ограничивающий параллелепипед кости фрейма и смещение

//соединения

void GetBoundingBoxSize(D3DXFRAME_EX *pFrame, D3DXMESHCONTAINER_EX *pMesh, D3DXVECTOR3 *vecSize,

D3DXVECTOR3 *vecJointOffset);

// Создать кость и установить ее данные void BuildBoneData(DWORD *BoneNum,

D3DXFRAME_EX *Frame, D3DXMESHCONTAINER_EX *pMesh, cRagdollBone *ParentBone = NULL);

// Установить силы тяжести, амортизации и соединения void SetForces(DWORD BoneNum,

D3DXVECTOR3 *vecGravity, float LinearDamping, float AngularDamping);

//Объединить движение кости для промежутка времени void Integrate(DWORD BoneNum, float Elapsed);

//Обработать столкновения

DWORD ProcessCollisions(DWORD BoneNum, cCollision *pCollision, D3DXMATRIX *matCollision);

// Обработать соединения костей

void ProcessConnections(DWORD BoneNum);

// Преобразовать точки состояния void TransformPoints(DWORD BoneNum);

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

224

Глава 7

D3DX спросите вы? Ну, функции CrossProduct и Transform используют D3DX, но я хотел иметь возможность вычислять векторное произведение и преобразование векторов напрямую в других кодах, как показано тут:

D3DXVECTOR3 vecResult = Transform(&CrossProduct(&vec1, \ &vec2), \

&matTransform);

Третья защищенная функция GetBoundingBoxSize используется для вычисления размера ограничивающего параллелепипеда кости. Этот параллелепипед содержит все вершины, присоединенные к кости и точки присоединения кости к родителю и потомкам (если таковые имеются). Следующая функция SetForces используется для установки начальных сил, действующих на тело: тяжести, линейной и угловой амортизации.

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

вглобальные координаты, используя ориентацию и положение кости, хранящиеся

вобъекте состояния кости m_State).

Вы обнаружите полный исходный код класса cRagdoll, а также других определенных здесь классов, в файлах Ragdoll.cpp и Ragdoll.h компакт-диска этой книги. Рассмотренные пока функции просто дублировали сказанное ранее в этой главе, поэтому нет нужды в их объяснении. Ну, за исключением функций GetBoundingBoxSize и Integrate. Я вернусь к ним немного позже; а пока, я хочу продолжить, показав вам оставшиеся функции класса cRagdoll.

public:

cRagdoll();

~cRagdoll();

//создать куклу из предоставленного указателя иерархии фреймов BOOL Create(D3DXFRAME_EX *Frame,

D3DXMESHCONTAINER_EX *Mesh,

D3DXMATRIX *matInitialTransformation = NULL);

//Освободить данные куклы void Free();

//Обновить куклу, используя гравитацию и амортизацию void Resolve(float Elapsed,

float LinearDamping = -0.04f, float AngularDamping = -0.01f,

Созданиекукольнойанимации

D3DXVECTOR3 *vecGravity = &D3DXVECTOR3(0.0f, -9.8f, 0.0f), cCollision *pCollision = NULL,

D3DXMATRIX *matCollision = NULL);

//Перестроить иерархию фреймов void RebuildHierarchy();

//Функции, возвращающие количество костей и указатель на

//заданную кость

DWORD GetNumBones();

cRagdollBone *GetBone(DWORD BoneNum);

};

Нe беря во внимание конструктор и деструктор класса, которые используются для очистки и освобождения данных класса, вашему вниманию предоставляется шесть функций. Первая функция Create предназначена для установки данных класса. Установка включает в себя просмотр всех костей в иерархии фреймов и создание объекта кости твердого тела (cRagdollBone) для каждой. После этого кости преобразовываются таким образом, чтобы их положение и ориентация соответствовала фреймам. После создания объектов костей, вы можете освободить данные куклы, вызвав Free.

Между вызовами Create и Free вы в основном имеете дело с функцией Resolve. Эта функция принимает в качестве параметров количество обрабатываемых секунд, величину применяемой линейной и угловой амортизации, используемый вектор силы тяжести и указатель на массив объектов столкновений, используемых для проверки столкновений.

После вычисления части симуляции при помощи функции Resolve вы вызываете RebuildHierarchy для обновления иерархии фреймов. После ее обновления вы можете обновлять скелетный меш и визуализировать его!

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

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

Соседние файлы в предмете Программирование на C++