Третий и последний класс, используемый для управления системой кукольных анимаций, большой, поэтому я буду показывать его вам по частям. Сначала у вас есть указатель на иерархию фреймов, который используется для создания твердых тел при моделировании. У вас также имеется количество костей, содержащихся в иерархии костей, и массив объектов 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), которые вы используете для вычисления векторного произведения и преобразования векторов, используя матрицу преобразования и дополнительный вектор перемещения. Почему просто не использовать функции

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

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

&vec2), \ &matTransform);

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

Далее в списке функций идет Integrate, которая обрабатывает действующие на кость силу и момент, обновляет скорости и моменты и перемещает точки твердого тела в новое положение в зависимости от движения тела. Далее идут ProcessColli-sions (которая выполняет обнаружение столкновений и ответную реакцию на них), 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);

};

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

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

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

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

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

Хранение костей || Оглавление || Создание данных костей