DirectX 10 学习笔记6:渲染3D模型

之前我们只画了一个三角形,弱爆了。。现在琢磨绘制模型。

三维模型文件格式很多,但这里我们定义一种自己的简单格式:文件起始部分是顶点个数,然后每个顶点对应一行数据,该行数据包括顶点的坐标,纹理坐标以及法向量。每三行构成一个三角形面。比如下面的立方体模型,它包括了12个面,所以数据部分有36行,每三行代表一个三角形。

Cube.txt

Vertex Count: 36

Data:

-1.0  1.0 -1.0 0.0 0.0  0.0  0.0 -1.0
1.0  1.0 -1.0 1.0 0.0  0.0  0.0 -1.0
-1.0 -1.0 -1.0 0.0 1.0  0.0  0.0 -1.0
-1.0 -1.0 -1.0 0.0 1.0  0.0  0.0 -1.0
1.0  1.0 -1.0 1.0 0.0  0.0  0.0 -1.0
1.0 -1.0 -1.0 1.0 1.0  0.0  0.0 -1.0
1.0  1.0 -1.0 0.0 0.0  1.0  0.0  0.0
1.0  1.0  1.0 1.0 0.0  1.0  0.0  0.0
1.0 -1.0 -1.0 0.0 1.0  1.0  0.0  0.0
1.0 -1.0 -1.0 0.0 1.0  1.0  0.0  0.0
1.0  1.0  1.0 1.0 0.0  1.0  0.0  0.0
1.0 -1.0  1.0 1.0 1.0  1.0  0.0  0.0
1.0  1.0  1.0 0.0 0.0  0.0  0.0  1.0
-1.0  1.0  1.0 1.0 0.0  0.0  0.0  1.0
1.0 -1.0  1.0 0.0 1.0  0.0  0.0  1.0
1.0 -1.0  1.0 0.0 1.0  0.0  0.0  1.0
-1.0  1.0  1.0 1.0 0.0  0.0  0.0  1.0
-1.0 -1.0  1.0 1.0 1.0  0.0  0.0  1.0
-1.0  1.0  1.0 0.0 0.0 -1.0  0.0  0.0
-1.0  1.0 -1.0 1.0 0.0 -1.0  0.0  0.0
-1.0 -1.0  1.0 0.0 1.0 -1.0  0.0  0.0
-1.0 -1.0  1.0 0.0 1.0 -1.0  0.0  0.0
-1.0  1.0 -1.0 1.0 0.0 -1.0  0.0  0.0
-1.0 -1.0 -1.0 1.0 1.0 -1.0  0.0  0.0
-1.0  1.0  1.0 0.0 0.0  0.0  1.0  0.0
1.0  1.0  1.0 1.0 0.0  0.0  1.0  0.0
-1.0  1.0 -1.0 0.0 1.0  0.0  1.0  0.0
-1.0  1.0 -1.0 0.0 1.0  0.0  1.0  0.0
1.0  1.0  1.0 1.0 0.0  0.0  1.0  0.0
1.0  1.0 -1.0 1.0 1.0  0.0  1.0  0.0
-1.0 -1.0 -1.0 0.0 0.0  0.0 -1.0  0.0
1.0 -1.0 -1.0 1.0 0.0  0.0 -1.0  0.0
-1.0 -1.0  1.0 0.0 1.0  0.0 -1.0  0.0
-1.0 -1.0  1.0 0.0 1.0  0.0 -1.0  0.0
1.0 -1.0 -1.0 1.0 0.0  0.0 -1.0  0.0
1.0 -1.0  1.0 1.0 1.0  0.0 -1.0  0.0

由于现在模型类的数据不再是硬编码,而是从文件读入,所以首先模型类要进行一些改动。

首先要有存储顶点数据的对应结构,所以要在模型类中先定义存储顶点数据的结构体,并添加一个指针,该指针指向存储顶点数据的数组:

class ModelClass
{
private:
    ...
    struct ModelType
    {
        float x, y, z;
        float tu, tv;
        float nx, ny, nz;
    };
    ModelType* m_model;
    ...
};

另外,初始化的时候要读文件,所以初始化函数的参数需要改变,加一个文件名参数:

 

bool Initialize(ID3D10Device*, char*, WCHAR*);

模型的实际加载和释放通过两个私有函数完成:

bool LoadModel(char*);
void ReleaseModel();

模型类实现部分的对应改动及新添加函数的实现:

构造函数中:

ModelClass::ModelClass()
{
    ...
    m_model = NULL;
}

初始化函数:

bool ModelClass::Initialize(ID3D10Device* device, char* modelFilename, WCHAR* textureFilename)
{
    bool result;
    result = LoadModel(modelFilename);
    if(!result)
    {
        return false;
    }
    ...
}

资源释放:

 

void ModelClass::Shutdown()
{
    ...
    ReleaseModel();
}

以前的InitializeBuffers函数中,顶点数和顶点坐标等数据是硬编码的,现在这些数据已经从文件读取,所以在初始化缓存的时候只需要把从文件读出来的数据拷贝到缓冲区中,顶点数也不需要在这里指定了(在后面的LoadModel函数中读取文件的时候赋值):

bool ModelClass::InitializeBuffers(ID3D10Device* device)
{
    ...
    // Load the vertex array and index array with data.
    for(i=0; i<m_vertexCount; i++)
    {
        vertices[i].position = D3DXVECTOR3(m_model[i].x, m_model[i].y, m_model[i].z);
        vertices[i].texture = D3DXVECTOR2(m_model[i].tu, m_model[i].tv);
        vertices[i].normal = D3DXVECTOR3(m_model[i].nx, m_model[i].ny, m_model[i].nz);
 
        indices[i] = i;
    }
    ...
}

 

LoadModel函数的实现:

bool ModelClass::LoadModel(char* filename)
{
    ifstream fin;
    char input;
    int i;
 
 
    // Open the model file.
    fin.open(filename);
    
    // If it could not open the file then exit.
    if(fin.fail())
    {
        return false;
    }
 
    // Read up to the value of vertex count.
    fin.get(input);
    while(input != ':')
    {
        fin.get(input);
    }
 
    // Read in the vertex count.
    fin >> m_vertexCount;
 
    // Set the number of indices to be the same as the vertex count.
    m_indexCount = m_vertexCount;
 
    // Create the model using the vertex count that was read in.
    m_model = new ModelType[m_vertexCount];
    if(!m_model)
    {
        return false;
    }
 
    // Read up to the beginning of the data.
    fin.get(input);
    while(input != ':')
    {
        fin.get(input);
    }
    fin.get(input);
    fin.get(input);
 
    // Read in the vertex data.
    for(i=0; i<m_vertexCount; i++)
    {
        fin >> m_model[i].x >> m_model[i].y >> m_model[i].z;
        fin >> m_model[i].tu >> m_model[i].tv;
        fin >> m_model[i].nx >> m_model[i].ny >> m_model[i].nz;
    }
 
    // Close the model file.
    fin.close();
 
    return true;
}

 

ReleaseModel:

void ModelClass::ReleaseModel()
{
    if(m_model)
    {
        delete [] m_model;
        m_model = 0;
    }
 
    return;
}

 

剩下的,只需要对视图类初始化时所调用的Initialize函数参数进行修改即可。第二个参数是模型文件的路径。

posted on 2013-01-23 20:54  youthlion  阅读(1477)  评论(0编辑  收藏  举报

导航