Для визуализации морфируемых мешей вам необходимо установить исходный и целевой потоки вершин. Также вам необходимо установить индексы только исходного меша. Это можно сделать простым перебором каждого набора и визуализированием их многоугольников.
Подождите-ка! Как визуализировать меш самостоятельно? Повторив то, что делает функция ГО3ВХМе8п::Бга\у8иЬ8е1, конечно же! Функция БгалуБгйьзе! работает, используя один из двух методов. В первом режиме, применяемом, если меш не оптимизирован для использования таблицы атрибутов, просматривается весь список атрибутов и визуализируются те многоугольники, которые принадлежат одному подна-бору. Этот метод может быть немного медленным, потому что он визуализирует меши, использующие множество материалов, маленькими наборами многоугольников.
Второй метод, применяемый после оптимизации меша для использования таблицы атрибутов, просматривает созданную таблицу атрибутов для определения, какие группы граней могут быть нарисованы одновременно. Таким образом, все грани принадлежащие одному поднабору сначала группируются, а потом визуализируются одним вызовом функции DrawPrimitive или DrawIndexedPrimmve. Похоже, это мы и будем использовать!
Чтобы использовать второй метод визуализации, необходимо сначала оптимизировать исходный меш. Вы можете (и должны) сделать это при загрузке меша. Можно безопасно оптимизировать все загруженные меши, используя функцию ID3DXMesh::OptimizeInPlace, как показано тут:
// pMesh = только что загруженный меш pMesh->OptimizeInPlace(D3DXMESHOPT_ATTRSORT, \ NULL, NULL, NULL, NULL) ;
После оптимизации меша вы можете получить таблицу атрибутов, используемую объектом ID3DXMesh. Таблица атрибутов имеет тип D3DXATTRIBUTERANGE, который определен так:
typedef struct _D3DXATTRIBUTERANGE { DWORD Attribld;
DWORD FaceStart; DWORD FaceCount;
DWORD VertexStart; DWORD VertexCount;
} D3DXATTRIBUTERANGE;
Первая переменная Attribld является номером поднабора, который представляет структура. Каждый материал меша ассоциирован с одной структурой D3DXATTRIBUTERANGE, Attribld которой указывает номер поднабора.
Далее идет FaceStart и FaceCount. Эти две переменные используются для определения, какие грани принадлежат поднабору. Вот где и появляется оптимизация - все грани, принадлежащие одному и тому же поднабору, группируются в буфере индексов. FaceStart представляет собой первую грань, принадлежащую поднабору, в то время как FaceCount содержит количество граней, визуализируемых в данном поднаборе.
Наконец вы обнаружите VertexStart и VertexCount, которые совсем как FaceStart и FaceCount определяют, какие вершины используются при визуализации многоугольников. VertexStart представляет собой первую вершину из буфера вершин, используемую в поднаборе, a VertexCount содержит количество вершин, визуализируемых за один раз. Когда вы оптимизируете меш, основываясь на вершинах, вы заметите, что все вершины запакованы в буфере для уменьшения количества вершин, используемых при визуализации поднабора.
Для каждого поднабора вашего меша существует соответствующая структура D3DXATTRIBUTERANGE. Таким образом, меш, использующий три материала, имеет три структуры атрибутов. После оптимизации меша (используя ID3DXMesh::OptimizeInPlace) вы можете получить таблицу атрибутов, сначалавзяв из объекта меша количество структур атрибутов, используя функцию ID3DXMesh::GetArtribute-Table, как показано тут:
// Получить количество атрибутов в таблице DWORD NumAttributes;
pMesh->GetAttributeTable(NULL, &NumAttributes);
Теперь вам необходимо просто создать необходимое количество объектов D3DXATTRIBUTERANGE и вызвать функцию GetAttributeTable, указав, на этот раз, указатель на массив объектов атрибутов.
// Выделить память под таблицу атрибутов и получить ее данные D3DXATTRIBUTERANGE *pAttributes;
pAttributes = new D3DXATTRIBUTERANGE[NumAttributes]; pMesh->GetAttributeTable(pAttributes, NumAttributes) ;
Замечательно! После того как вы получили данные атрибутов, вы можете визуализировать поднаборы, просматривая каждый объект таблицы атрибутов и используя данные каждого из них при вызове DrawIndexedPrimitive. На самом деле вам необходимо сначала получить указатели на буферы вершин и индексов меша.
// Получить интерфейс буфера вершин IDirect3DVertexBuffer9 *pVB; pMesh->GetVertexBuffer(&pVB);
// Получить интерфейс буфера индексов IDirect3DIndexBuffer9 *pIB; pMesh->GetIndexBuffer(&pIB);
После того как вы получили оба указателя, вы можете смело устанавливать потоки, вершинные шейдеры и объявления элементов вершин, просматривать каждый набор, устанавливая текстуру, после чего визуализировать многоугольники.
// Установить вершинный шейдер и объявления
pDevice->SetFVF(NULL); // Clear FVF usage
pDevice->SetVertexShader(pShader); pDevice->SetVertexDeclaration(pDecl);
// Установить потоки
pDevice->SetStreamSource(0, pVB, \
0, pMesh->GetNumBytesPerVertex()); pDevice->SetIndices(pIB) ;
// Просмотреть каждый поднабор
for(DWORD i=0;i<NumAttributes;i++) {
// Получить номер материала
DWORD MatID = pAttributes[i];
// Установить текстуру поднабора pDevice->SetTexture(0, pTexture[AttribID]);
// Визуализировать многоугольник, используя таблицу pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, \
pAttributes[i].VertexStart, \
pAttributes[i].VertexCount, \
pAttributes[i].FaceStart * 3, \
pAttributes[i].FaceCount);
}
После того как вы визуализировали ваши поднаборы, вы можете освободить полученные ранее интерфейсы буферов вершин и индексов.
pVB->Release(); pVB = NULL; pIB->Release(); pIB = NULL;
Когда вы закончите работу с таблицей атрибутов, убедитесь, что тоже освободили ее.
delete [] pAttributes; pAttributes = NULL;
Замечательно, вы уже кое-что знаете! После того как вы узнали, как самостоятельно визуализировать поднаборы, пришло время перейти к использованию вершинных шейдеров.
⇐Визуализация морфированных мешей || Оглавление || Создание морфирующего вершинного шейдера⇒