Предположим, что вы уже загрузили меш в объект ID3DXMesh, и из него вы собираетесь создавать объект одежды. В предыдущем разделе я определили две переменные, определяющие размеры массивов точек и пружин - NumPoints и NumSprings. В том разделе эти переменные были не определены, но теперь, имея корректный объект меша (предположим, что он называется pClothMesh), вы можете получить из него информацию, необходимую для вычисления этих переменных так:
// pClothMesh = предварительно загруженный объект ID3DXMesh NumPoints = pClothMesh->GetNumVertices(); NumSprings = pClothMesh->GetNumFaces() * 3;
После того как вы определили количество точек и пружин, содержащихся в массивах одежды, можно начинать перемещение данных вершин для конструирования массива. Первым шагом к получению данных вершин меша является вычисление размера каждой его вершины, при помощи D3DXGetFVFVertexSize, как показано тут:
DWORDVertexStide=D3DXGetFVFVertexSize(pClothMesh->GetFVF());
Когда вы знаете размер вершины (называемый шагом вершины), вы можете заблокировать буфер вершин меша, получив таким образом указатель на его данные, через который можно обращаться к вершинам. Используя указатель на данные буфера вершин, вы можете просмотреть все вершины меша и получить их координаты (первые три вещественных значения каждой частицы).
Так зачем же необходимо вычислять размер каждой вершины? Когда вы просматриваете вершины, находящиеся в буфере вершин, вы не знаете, сколько данных содержит каждая вершина. Т. к. нас интересуют только координаты вершин, можно использовать их размер для пропуска ненужных данных и перехода к следующей вершине в списке.
Замечание. На самом деле использование количества граней для определения количества создаваемых пружин одежды является не очень хорошей идеей. Т. к. каждая грань меша может разделять любое количество вершин, то получается множество повторяющихся пружин. Далее в этой главе я покажу вам способ создания пружин, который позволяет избежать повторений.
После того как мы выяснили, для чего используется размер вершины, попробуем заблокировать буфер вершин, получить указатель на данные и просмотреть список вершин.
// Создать универсальную структуру вершин для получения координат typedef struct {
D3DXVECTOR3vecPos ; } sVertex;
// Заблокировать буфер вершин BYTE *pVertices;
pClothMesh->LockVertexBuffer(D3DLOCK_READONLY, \ (BYTE**)&pVertices);
/ / Просмотреть список вершин и получить их координаты for(DWORD i = 0;i<NumPoints;i + +) {
// Преобразовать к структуре универсальной вершины sVertex *pVertex = (sVertex*)pVertices;
/ / Сохранить координаты точки одежды ClothPoints[i].m_vecPos=pVertex->vecPos;
Также необходимо определить массу точки. Т. к. нет никакого источника этого значения (т. к. меш не содержит значений массы), можно просто установить какое-нибудь значение по умолчанию, скажем 1. То же самое относится и к другим значениям массы (m_OneOverMass) - установите их в 1, деленную на массу.
// Присвоить массу, равную единице, и 1/масса ClothPoints[i].m_Mass = 1.0f;
ClothPoints[i].m_OneOverMass = 1.0f / ClothPoints[i].m_Mass;
После установки двух значений массы можно переходить к следующей вершине и точке и продолжать так то тех пор, пока все точки одежды не будут инициализированы соответствующими данными. После этого можно разблокировать буфер вершин и продолжать, как показано тут:
// Перейти к следующей вершине в списке pVertices += VertexStride; }
// Разблокировать буфер вершин pClothMesh->UnlockVertexBuffer();
Замечательно, мы уже на полпути к получению необходимых данных одежды, используемых при симуляции! Далее необходимо преобразовать ребра меша в пружины, которые бы скрепляли одежду. На этот раз необходимо заблокировать буфер индексов меша и получить три индекса, образующих каждую грань. Три точки соединяются, образуя грани, при этом каждая грань является пружиной.
Получить доступ к буферу индексов намного проще, чем получить доступ к буферу вершин. Я полагаю, что используются 16-битные индексы, потому что 32-битные индексы пока не очень широко распространены. Необходимо получить следующие подряд 16-битные значения индексов для каждой грани и создать из них три пружины, используя все сочетания соединений каждых двух имеющихся индексов.
Можно начать, заблокировав буфер индексов.
unsigned short *pIndices;
pClothMesh->LockIndexBuffer(D3DLOCK_READONLY, \ (BYTE**)&pIndices) ;
Теперь необходимо просмотреть все грани и получить три индекса, образующие каждую из них. (Также необходимо объявить переменную, которая бы следила за создаваемой в данный момент пружиной.)
DWORD SpringNum = 0;
for(i=0;i<pClothMesh->GetNumFaces();i++) { unsigned short Indexl = *pIndices++; unsigned short Index2 = *pIndices++; unsigned short Index3 = *pIndices++;
Используя эти три индекса, создайте три пружины, представляющие собой грани.
// Создать пружину от 1->2
ClothSprings[SpringNum].m_Point1 = Index1; ClothSprings[SpringNum].m_Point2 = Index2; SpringNum++; // Увеличить число пружин
// Создать пружину от 2->3
ClothSprings[SpringNum].m_Point1 = Index2; ClothSprings[SpringNum].m_Point2 = Index3; SpringNum++; // Увеличить число пружин
/ / Создать пружину от 1->3
ClothSprings[SpringNum].m_Point1 = Indexl; ClothSprings[SpringNum].m_Point2 = Index3; SpringNum++; // Увеличить число пружин
}
После того как вы закончите обрабатывать все индексы и пружины, необходимо еще раз просмотреть список пружин, вычислив длину покоя каждой из них. Эта длина является расстоянием между точками, вычисляемым при помощи никому не известной1 теоремы Пифагора, которая гласит, что сумма квадрата гипотенузы равна сумме квадратов катетов. Нет нужды искать эту теорему и код, ее реализующий, в книжках по математике, вместо этого вы можете использовать D3DX, как в следующем коде:
for(i=0;i<NumSprings;i++) {
// Получить индексы каждой точки пружины unsigned short Pointl = ClothSprings[i].m_Point1; unsigned short Point2 = ClothSprings[i].m_Point2;
// Вычислить векторную разность точек
D3DXVECTOR3 vecDiff = ClothPoints[Point2].m_vecPos - / ClothPoints[Point1].m_vecPos;
// Использовать D3DX для вычисления длины вектора разности ClothSprings[i].m_RestingLength = D3DXVec3Length(&vecDiff);
}
Наконец вы закончили создавать точки и пружины одежды! Теперь можно переходить к рассмотрению их движения!
⇐Определение точек одежды и пружин || Оглавление || Приложение сил для создания движения⇒