六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 357|回复: 0

Directx11教程(67) 显示模型文件

[复制链接]

升级  91.33%

154

主题

154

主题

154

主题

举人

Rank: 3Rank: 3

积分
474
 楼主| 发表于 2012-12-30 11:52:21 | 显示全部楼层 |阅读模式
Directx11教程(67) 显示模型文件

<div class="postbody"><div id="cnblogs_post_body">      在前面的教程中,我们都是通过在ModelClass中直接产生顶点和索引数据,简单的三角形,立方体等等还好说,毕竟比较简单,如何显示复杂的三维物体呢?特别是利用已有的3D文件,比如obj, 3ds, md2, x等格式的文件,这时,就要利用这些3D格式的解析器,本教程中,我们利用Open Asset Import Library库,来显示各种格式的3D文件(动画文件,暂时不考虑,只考虑静态的3D文件)。
        Open Asset Import Library是一个开源的模型导入库,支持很多格式,它的下载和安装就不介绍了,下面我再myTutorialD3D11_35的基础上,加入使用Assimp库导入3D文件的代码。
  
     主要就是增加了一个AssimpModelClass类,该类中顶点格式为:

  {     
D3DXVECTOR3 position;      
D3DXVECTOR3 normal; //法向      
D3DXVECTOR2 texture; //纹理坐标      
D3DXVECTOR4 Kd;  //材质漫反射系数      
D3DXVECTOR4 Ks;  //材质的高光系数      
};
   

   
  产生顶点和索引缓冲的函数为AssimpModelClass,我们通过该函数产生顶点缓冲和索引缓冲。
  bool  AssimpModelClass::LoadModel(ID3D11Device* device, std::string filename)     
{      
    HRESULT result;

  注意:首先我们会定义一个assimp导入器类,用该类读入模型文件,我们会做2趟循环,第一趟循环得到顶点和索引的数量,然后创建顶点和索引临时缓冲,用来保存顶点和索引数据,第二趟循环从模型文件中读取顶点和索引的数据,最后创建顶点和索引缓冲。      
    Assimp::Importer importer;      
    VertexType* vertices;      
    unsigned long* indices;      
    D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;      
    D3D11_SUBRESOURCE_DATA vertexData, indexData;

     
    const aiScene* scene = importer.ReadFile(filename,aiProcessPreset_TargetRealtime_Quality);      
   
    if(!scene)      
    {      
        MessageBoxA(NULL, importer.GetErrorString(), "Error", MB_OK);      
        return false;      
    }

      int m =0;     
    //第一趟扫描,得到顶点和索引计数      
    for(m=0; m<scene->mNumMeshes; ++m )      
    {      
        //第m个mesh      
        aiMesh* aiMesh = scene->mMeshes[m];

          m_vertexCount += aiMesh->mNumVertices;     
        m_indexCount  += aiMesh->mNumFaces*3;      
    }

      // 创建顶点临时缓冲.      
    vertices = new VertexType[m_vertexCount];      
    if(!vertices)      
    {      
        return false;      
    }

      // 创建索引临时缓冲.      
    indices = new unsigned long[m_indexCount];      
    if(!indices)      
    {      
        return false;      
    }

      //临时的顶点和索引指针      
    int index1 = 0;      
    int index2 = 0;      
    int i = 0;

      //第二趟循环,得到每个顶点和索引的值      
    for(m=0; m<scene->mNumMeshes; ++m )      
    {      
        //第m个mesh      
        aiMesh* aiMesh = scene->mMeshes[m];

          if(!aiMesh->HasNormals() || !aiMesh->HasTextureCoords(0))     
        {      
            MessageBox(NULL, L"模型文件中没有纹理坐标或者法向信息", L"Error", MB_OK);      
            return false;      
        }

          int vertexCount = aiMesh->mNumVertices;     
        for(i = 0;i < vertexCount;++i)      
        {      
            vertices[index1].position = D3DXVECTOR3(aiMesh->mVertices.x, aiMesh->mVertices.y, aiMesh->mVertices.z);      
            vertices[index1].normal = D3DXVECTOR3(aiMesh->mNormals.x, aiMesh->mNormals.y, aiMesh->mNormals.z);      
            vertices[index1].texture = D3DXVECTOR2(aiMesh->mTextureCoords[0].x, aiMesh->mTextureCoords[0].y);      
            vertices[index1].Kd = D3DXVECTOR4(1.0, 1.0, 1.0,1.0);      
            vertices[index1].Ks = D3DXVECTOR4(0.2, 0.2, 0.2,1.0);      
            index1++;      
        }

          for (i = 0; i < aiMesh->mNumFaces;++i)     
        {      
            const aiFace& Face = aiMesh->mFaces;      
            //assert(Face.mNumIndices == 3);      
            indices[index2] = Face.mIndices[0];      
            index2++;      
            indices[index2] = Face.mIndices[1];      
            index2++;      
            indices[index2] = Face.mIndices[2];      
            index2++;

          }     
    }      
    // 设置顶点缓冲描述      
    vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;      
    vertexBufferDesc.ByteWidth = sizeof(VertexType) * m_vertexCount;      
    vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;      
    vertexBufferDesc.CPUAccessFlags = 0;      
    vertexBufferDesc.MiscFlags = 0;      
    vertexBufferDesc.StructureByteStride = 0;

      // 指向保存顶点数据的临时缓冲.      
    vertexData.pSysMem = vertices;      
    vertexData.SysMemPitch = 0;      
    vertexData.SysMemSlicePitch = 0;

      // 创建顶点缓冲.      
    result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer);      
    if(FAILED(result))      
    {      
        HR(result);      
        return false;      
    }

      // 设置索引缓冲描述.      
    indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;      
    indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;      
    indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;      
    indexBufferDesc.CPUAccessFlags = 0;      
    indexBufferDesc.MiscFlags = 0;      
    indexBufferDesc.StructureByteStride = 0;

      // 指向存临时索引缓冲.      
    indexData.pSysMem = indices;      
    indexData.SysMemPitch = 0;      
    indexData.SysMemSlicePitch = 0;

      // 创建索引缓冲.      
    result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer);      
    if(FAILED(result))      
    {      
        HR(result);      
        return false;      
    }

      // 释放临时缓冲.      
    delete [] vertices;      
    vertices = 0;

      delete [] indices;     
    indices = 0;

      return true;
  }
       随后在GraphicsClass中,我们会增加AssimpModelClass变量,并用LightTexShader来渲染该类装入的模型,主要的代码如下:
  1、初始化的代码
  // 创建assimp模型对象      
m_AssimpModel = new AssimpModelClass;      
if(!m_AssimpModel)      
    {      
    return false;      
    }      
// 初始化坐标assimp模型对象.faerie.md2,tiny.x      
result = m_AssimpModel->Initialize(m_D3D->GetDevice(), "tiny.x");      
if(!result)      
    {      
    MessageBox(hwnd, L"Could not initialize the axis model object.", L"Error", MB_OK);      
    return false;      
    }
   

  2、渲染的代码:
  D3DXMatrixScaling(&worldMatrix4, 0.02, 0.02,0.02);
  m_AssimpModel->Render(m_D3D->GetDeviceContext());     
//用light shader渲染,faerie2.bmp,Tiny_skin.dds      
result = m_LightTexShader->Render(m_D3D->GetDeviceContext(), m_AssimpModel->GetIndexCount(), worldMatrix4, viewMatrix, projectionMatrix,      
             light, material, camera,m_TexManager->createTex(m_D3D->GetDevice(),string("Tiny_skin.dds")));      
if(!result)      
    {      
    return false;      
    }
   

  程序执行后的效果图如下:
  装入x格式文件tiny.x
  
  装入md2格式文件faerie.md2
  
       
  完整的代码请参考:
  工程文件myTutorialD3D11_64
  代码下载:
  稍后提供
  
   
   
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表