Издательский дом ООО "Гейм Лэнд"СПЕЦВЫПУСК ЖУРНАЛА ХАКЕР #64, МАРТ 2006 г.

dead can dance

ФЛЕНОВ МИХАИЛ AKA HORRIFIC

Спецвыпуск: Хакер, номер #064, стр. 064-052-4


фреймы

Остановимся подробнее на шестом параметре функции D3DXLoadMeshHierarchyFromX, где мы получаем указатель на массив структур D3DXFRAME. Что это такое? На самом деле каждая такая структура описывает определенную кость в скелете и выглядит следующим образом:

typedef struct _D3DXFRAME {

LPTSTR Name;

D3DXMATRIX TransformationMatrix;

LPD3DXMESHCONTAINER pMeshContainer;

struct _D3DXFRAME *pFrameSibling;

struct _D3DXFRAME *pFrameFirstChild;

} D3DXFRAME, *LPD3DXFRAME;

Что же есть в этой структуре и для чего «оно» предназначено?

Name — имя элемента скелета. Каждая кость может иметь свое имя, по которому достаточно удобно находить именно ту часть скелета, которая требует вращения. Зная имя кости, ты легко найдешь ее структуру, перебрав весь скелет. Указатели на наиболее часто используемые структуры лучше сохранить в глобальных переменных, и тогда ты не будешь каждый раз перебирать весь скелет, следовательно, повысишь скорость анимации.

TransformationMatrix — матрица преобразований. Определяет положение данной косточки.

pMeshContainer — указатель на контейнер сетки.

pFrameSibling — указатель на следующую структуру D3DXFRAME, которая находится на том же уровне. Например, все пальцы находятся на одном и том же уровне иерархии скелета, через этот указатель можно последовательно получать доступ к ним.

pFrameFirstChild — указатель на первую кость, которая находится на уровень ниже.

в движении

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

рекурсивная функция

void Преобразовать(D3DXFRAME фрейм, D3DXMATRIX матрица)

{

// Перемножаем матрицы, т.е. объединяем

фрейм.TransformationMatrix *= матрица;

// Если есть родственники, то преобразовать их фреймы

if (фрейм.pFrameSibling)

Преобразовать(фрейм.pFrameSibling, матрица);

// Если есть дочерние, то преобразовать их фреймы

if (фрейм.pFrameFirstChild)

Преобразовать(фрейм. pFrameFirstChild, фрейм.TransformationMatrix);

}

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

советы

Реальный пример не рассматриваю, потому что экономлю место в журнале и боюсь сделать его слишком толстым. Если заинтересовался скелетной анимацией, обратись к примерам DX SDK, там посмотри примеры анимации для C++ и C# (с использованием Managed DirectX). Вся необходимая база для понимания исходного кода примера у тебя уже есть.

Назад на стр. 064-052-3  Содержание  Вперед на стр. 064-052-5