Работа со скелетными мешами

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

Скелетные меши очень похожи на обычные, с которыми вы уже знакомы. Используя объект D3DXMESHCONTAINER_EX (как вы видели в главе 1), вы можете хранить данные ваших мешей от вершин и индексов до материалов и данных текстур, все это находится в удобном объекте ID3DXMesh. Что же касается фактических данных скелетного меша, они расположены в специальном объекте ID3DXSkinInfo.

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

Посмотрите на рис. 4.3, на котором изображен скелет, окруженный простейшим мешем.

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

Работа со скелетными мешами

Рис. 4.3. При присоединении к скелетной структуре меш изменяется таким образом, чтобы каждая вершина соединялась с костью

Внимательно посмотрев на рис. 4.3 вы обнаружите, что некоторые вершины присоединены к нескольким костям. Так и есть - вы можете присоединять вершину более чем к одной кости. На самом деле, при использовании DirectX вы можете присоединять вершину к неограниченному числу костей, используя методы, которые вы изучите в этой книге. При движении кости, к которой присоединена вершина, вершина наследует не все движения. Например, если кость поворачивается на 60 градусов по оси z, присоединенная к ней вершина может повернуться только на 25 процентов от этого, т.е вершина повернется только на 15 градусов по оси z.

Точное значение процентного соотношения наследуемого вершиной движения назьшается весом вершины. Для каждой вершины скелетного меша назначается ее вес при присоединении ее к кости. Для вершин, присоединенных только к одной кости, это значение обычно 1.0, это говорит о том, что вершина наследует все движениякости. Для вершин, присоединенных к нескольким костям, веса делятся на количество костей и, обычно, вычисляются, используя расстояние до каждой кости. (Большинство программ трехмерного моделирования сделает это за вас.) Например, вершина присоединена к двум костям, это означает, что оба веса будут по 0.5. Вершина будет наследовать только 50 процентов движения каждой кости. Заметьте, что сумма весов одной вершины всегда равняется 1.

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

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

1. Перебрать все вершины. Для каждой вершины выполнить шаг 2.

2. Для каждой кости, к которой присоединена вершина, получить преобразование.

3. Каждое преобразование кости умножить на матрицу вершинных весов и наложить полученное преобразование на комбинированное преобразование вершин.

4. Повторить шаг 3 для каждой присоединенной кости, шаги 2-4 повторить для всех вершин. После завершения применить комбинированную матрицу преобразования на заданную вершину (из шага 1).

И все таки, как получить веса вершин? Используя объект ID3DXSkinInfo, о котором я упоминал ранее, вы можете загружать веса из .X файлов. Скелетные веса хранятся в объекте Mesh, в конце его данных.

Каждой кости в скелетной структуре соответствует объект SkinWeights. Внутри объекта SkinWeights находится имя кости и следующее за ним количество присоединенных вершин. Заголовок скелетного меша определяет количество костей, к которым может быть присоединена каждая вершина. Если какая то из вершин присоединена к двум костям, тогда все вершины должны быть присоединены к двум костям. Для того чтобы вершины могли иметь разное количество костей, вы можете присваивать вес 0 ненужным костям.

Как я упоминал ранее, объект SkinWeights включает количество вершин, присоединенных к кости. Он перечисляет массив индексов вершин. После массива индексов вершин расположен массив значений весов вершин. Наконец, далее идет обратное преобразование костей для помощи в расположении вершин относительно соединений костей.

Посмотрите на пример объекта шаблона SkinWeights:

SkinWeights {

"Bip01_R_UpperArm"; 4;

0, 3449, 3429, 1738;

0.605239, 0.605239, 0.605239, 0.979129; -0.941743, -0.646748, 0.574719, 0.000000, -0.283133, -0.461979, -0.983825, 0.000000, 0.923060, -1.114919, 0.257891, 0.000000, -65.499557, 30.497688, 12.852692, 1.000000;;

}

В этом объекте используется кость "Bip01_R_UpperArm'\ К ней присоединены четыре вершины с индексами 0, 3449, 3429 и 1738. Вершина 0 имеет вес 0.605239, вершина 1 - 0.605239 и так далее. Матрица преобразования выравнивает перечисленные вершины относительно соединения костей. Эта матрица очень важна. Без нее вершины будут вращаться относительно центра мира, а не соединения костей.

К счастью, вам не нужно напрямую работать с шаблоном SkinWeights. Эти данные обрабатываются при загрузке скелетных мешей из .X файлов, используя функции D3DX.

Обновление иерархии || Оглавление || Загрузка скелетных мешей из .X