Когда ваша скелетная структура находится в желаемой позе, пришло время обновить (или восстановить) скелетный меш, чтобы он соответствовал ей. Прежде чем восстанавливать скелетный меш, вам необходимо убедиться, что контейнер вторичного меша создан и иерархия фреймов обновлена. Для повторения того, как создавать контейнер мешей, обратитесь к разделу "Создание контейнера вторичного меша", находящемуся ранее в этой главе. Чтобы освежить ваши воспоминания о том, как обновлять иерархию фреймов смотрите раздел "Обновление иерархии" ранее в этой главе. После того как вы их вспомните, вы можете продолжить.
Для обновления скелетного меша вы должны сначала заблокировать буферы вершин скелетного и вторичного меша. Это является очень важным, потому что DirectX возьмет данные вершин скелетного меша, наложит преобразования костей и запишет результирующие данные вершин в объект вторичного меша.
Однако сначала вам необходимо скопировать преобразования их фреймов в массив матриц (pBoneMatrices), хранимый в контейнере мешей. В то же самое время вам необходимо скомбинировать преобразования с обратным преобразованием костей. Обратное преобразование костей ответственно за перемещение вершин меша к его начальному положению, до того как вы примените фактические преобразования. Чтобы лучше понять это, посмотрите на рис. 4.4
На рис. 4.4 меш составлен их трех костей (фреймов) и некоторого количества вершин. Для применения преобразования к какому либо фрейму вам необходимо передвинуть вершины, принадлежащие фрейму, в начальное положение, а потом накладывать преобразования.
Вы перемещаете вершины относительно начального положения меша, прежде чем применять преобразования, т. к. матрица вращения просто поворачивает вершины относительно начального положения. Если бы вращали вершину, принадлежащую кости, вершина бы вращалась относительно начального положения меша, а не соединения костей. Например, если бы ваше тело было мешем, и вы бы согнули локоть, вершины, образующие меш руки, будут вращаться относительно локтя, а не центра вашего тела. После передвижения вершин к центру меша накладывается преобразование (чтобы поворот вершин соответствовал повороту костей) и, наконец, преобразовывается в положение.
Обычно, преобразования костей обратной матрицы хранятся в .X файле при использовании программы трехмерного моделирования для создания мешей. Если же это информация не содержится в .X файле, вы можете вычислить ее сами, сначала обновив иерархию фреймов, после чего обратив комбинированное преобразование фреймов, используя функцию D3DXMatrixInverse. Вот небольшой пример:

Рис. 4.4. Вершины могут только вращаться вокруг начального положения меша. Прежде чем вы примените преобразования костей, вам необходимо создать преобразование, которое перемещало бы вершины к начальному положению меша
// pRoot = корневой объект D3DXFRAME_EX
// pMesh = объект D3DXMESHCONTAINER_EX, содержащий данные меша
// Обновление иерархии фреймов pRoot->UpdateHierarchy();
// Перебрать все кости для вычисления обратной матрицы for(DWORD i=0;i<NumBones;i++) {
// Получить преобразование, используя матрицу кости
D3DXMATRIX matBone = (*pMesh->ppFrameMatrices);
// Обратить матрицу
D3DXMatrixInverse(&matBone, NULL, &matBone) ;
// Сохранить где-нибудь матрицу обратного преобразования кости }
Однако вместо того чтобы вычислять все эти матрицы обратного преобразования костей самостоятельно, вы можете использовать объект скелетного меша для получения этой информации. Вызвав ID3DXSkinInfo::GetBoneOffsetMatrix, вы получите указатель на обратную матрицу преобразования кости. Умножив эту матрицу на матрицу преобразования фрейма, вы получите необходимый результат.
Используя только что приобретенные знания, переберите все кости, получите их обратное преобразование, скомбинируйте его с преобразованием фрейма и сохраните результат в массиве pBoneMatrices.
for(DWORD i=0;i<pSkinInfo->GetNumBones();i++) { // Установить обратное преобразование кости
pMesh->pBoneMatrices[i]=(*pSkinInfo->GetBoneOffsetMatrix(i));
/ / Наложить преобразование фрейма if(pMesh->ppFrameMatrices[i]) pMesh->pBoneMatrices[i] *= (*pMesh->ppFrameMatrices[i]);
}
После того как вы скопировали преобразования костей в массив pBoneMatrices, вы можете обновлять скелетные меши, сначала заблокировав буферы вершин для скелетного и вторичного меша.
// pSkinMesh = контейнер скелетного меша // pMesh = контейнер вторичного меша
// Заблокировать буферы вершин мешей void *SrcPtr, *DestPtr;
pSkinMesh->LockvertexBuffer(D3DLOCK_READONLY, (void**)&SrcPtr) ; pMesh->LockVertexBuffer(0, (void**)&DestPtr) ;
После того как вы заблокировали буферы вершин, вам необходимо вызвать ID3DXSkinInfo::UpdateSkinnedMesh, чтобы наложить все преобразования костей на вершины и записать результирующие данные в контейнер вторичного меша. После чего просто разблокируйте буферы вершин, и вы готовы к визуализации!
// pSkinInfo = информационный объект скелетного меша
// Обновить скелетный, меш используя заданные преобразования pSkinInfo->UpdateSkinnedMesh(pBoneMatrices, NULL, \ SrcPtr, DestPtr);
// Разблокировать буферы вершин мешей pSkinMesh->UnlockVertexBuffer(); pMesh->UnlockVertexBuffer() ;
⇐Управление скелетными мешами || Оглавление || Визуализация скелетных мешей⇒