从文件中加载模型
2023-06-15
前面的几个例子都是通过直接计算出模型的顶点来创建几何体,但这只适用于一些简单的几何体(球、立方体、圆柱体等),如果是一些复杂的模型就无法通过简单的计算来获取顶点。通常复杂的模型是通过一些 3D 建模软件制作,按照一些存储标准把制作好的模型存储在文本文件里面,然后在程序中直接读取。比如下面这个头骨模型的例子(skull.txt):
VertexCount:31076
TriangleCount:60339
VertexList(pos, normal)
{
0. 592978 1. 92413 -2. 62486 0. 572276 0. 816877 0. 0721907
0. 571224 1. 94331 -2. 66948 0. 572276 0. 816877 0. 0721907
0. 609047 1. 90942 -2. 58578 0. 572276 0. 816877 0. 0721907
…
}
TriangleList
{
0 1 2
3 4 5
6 7 8
…
}
我们可以直接从文件中读取所有的顶点和索引。其中 VertexList 中每个元素有 6 个值,前 3 个表示位置(pos)的坐标,后 3 个表示法线向量(normal,暂时还没有使用到)。
void SkullApp::BuildGeometryBuffers() {
std::ifstream fin("Models/skull.txt");
if (!fin) {
MessageBox(0, L"Models/skull.txt not found.", 0, 0);
return;
}
UINT vcount = 0;
UINT tcount = 0;
std::string ignore;
fin >> ignore >> vcount;
fin >> ignore >> tcount;
fin >> ignore >> ignore >> ignore >> ignore;
float nx, ny, nz;
XMFLOAT4 black(0.0f, 0.0f, 0.0f, 1.0f);
std::vector<Vertex> vertices(vcount);
for (UINT i = 0; i < vcount; ++i) {
fin >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
vertices[i].Color = black;
// Normal not used in this demo.
fin >> nx >> ny >> nz;
}
fin >> ignore;
fin >> ignore;
fin >> ignore;
mSkullIndexCount = 3 * tcount;
std::vector<UINT> indices(mSkullIndexCount);
for (UINT i = 0; i < tcount; ++i) {
fin >> indices[i * 3 + 0] >> indices[i * 3 + 1] >> indices[i * 3 + 2];
}
fin.close();
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex) * vcount;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = &vertices[0];
HR(md3dDevice->CreateBuffer(&vbd, &vinitData, &mVB));
//
// Pack the indices of all the meshes into one index buffer.
//
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT) * mSkullIndexCount;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = &indices[0];
HR(md3dDevice->CreateBuffer(&ibd, &iinitData, &mIB));
}
头骨演示程序:
* 未经同意不得转载。