模型类是世界空间中的表示物体的类,那么他的所做的事就是加载模型,移动模型,渲染模型
modelclass.h
1 #pragma once 2 3 #include <d3d11.h> 4 #include <d3dcompiler.h> 5 #include <D3DX11.h> 6 #include <xnamath.h> 7 #include<fstream> 8 using namespace std; 9 #pragma comment(lib,"d3dx11.lib") 10 #pragma comment(lib,"d3d11.lib") 11 #pragma comment(lib,"d3dcompiler.lib") 12 class modelclass 13 { 14 public: 15 modelclass(); 16 ~modelclass(); 17 18 void Render(ID3D11DeviceContext* context,XMMATRIX& viewmatrix, XMMATRIX& promatrix, D3D11_PRIMITIVE_TOPOLOGY geometry, 19 ID3D11VertexShader* vertexshader, ID3D11PixelShader* pixelshader); 20 bool Initialize(ID3D11Device *device, LPCWSTR model, LPCWSTR texture); 21 void Setposition(float x, float y, float z); 22 void RotationAxis(XMVECTOR axis, float angle); 23 void Shutdown(); 24 25 private: 26 bool Loadmodel(LPCWSTR file); 27 bool Loadtexture(LPCWSTR file, ID3D11Device* device); 28 29 struct vertex 30 { 31 XMFLOAT3 pos; 32 XMFLOAT2 tex; 33 }; 34 35 struct constantBuffer 36 { 37 XMMATRIX world; 38 XMMATRIX view; 39 XMMATRIX pro; 40 }; 41 42 ID3D11Buffer *m_vertexBuffer, *m_indexBuffer; 43 ID3D11Buffer *m_constantBuffer; 44 int m_vertexCount, m_indexCount; 45 ID3D11ShaderResourceView* m_Texture; 46 ID3D11SamplerState *m_samplerstate; 47 vertex* m_vertexlist; 48 XMMATRIX m_worldMatrix; 49 };
他的公共方法如前所述:Render()渲染模型,Initialize()初始化(加载模型),Setposition()移动模型,RotationAxis()绕轴旋转。
两个私有数据结构,顶点和常量缓存,分别是用来构造顶点缓存和常量缓存的。
私有成员:顶点缓存,索引缓存,常量缓存,顶点个数,索引个数,纹理源视图,取样器状态,顶点列表,及世界变换矩阵。
modelclass.cpp
1 #include "modelclass.h" 2 3 4 modelclass::modelclass() 5 { 6 m_worldMatrix = XMMatrixIdentity(); 7 } 8 9 10 modelclass::~modelclass() 11 { 12 } 13 14 15 bool modelclass::Initialize(ID3D11Device* device,LPCWSTR model,LPCWSTR texture) 16 { 17 HRESULT hr = S_OK; 18 bool m=Loadmodel(model); 19 bool t=Loadtexture(texture,device); 20 21 D3D11_BUFFER_DESC bd; 22 ZeroMemory(&bd, sizeof(bd)); 23 bd.Usage = D3D11_USAGE_DEFAULT; 24 bd.ByteWidth = sizeof(vertex)* m_vertexCount; 25 bd.BindFlags = D3D11_BIND_VERTEX_BUFFER; 26 bd.CPUAccessFlags = 0; 27 D3D11_SUBRESOURCE_DATA InitData; 28 InitData.pSysMem = m_vertexlist; 29 hr = device->CreateBuffer(&bd, &InitData, &m_vertexBuffer); 30 if (FAILED(hr)) 31 { 32 return false; 33 } 34 35 36 WORD *indices = new WORD[m_indexCount]; 37 for (int i = 0; i < m_indexCount; i++) 38 { 39 indices[i] = i; 40 } 41 D3D11_BUFFER_DESC bd1; 42 ZeroMemory(&bd1, sizeof(bd1)); 43 bd1.Usage = D3D11_USAGE_DEFAULT; 44 bd1.ByteWidth = sizeof(WORD)* m_indexCount; 45 bd1.BindFlags = D3D11_BIND_INDEX_BUFFER; 46 bd1.CPUAccessFlags = 0; 47 D3D11_SUBRESOURCE_DATA InitData1; 48 InitData1.pSysMem = indices; 49 hr = device->CreateBuffer(&bd1, &InitData1, &m_indexBuffer); 50 if (FAILED(hr)) 51 { 52 return false; 53 } 54 55 56 D3D11_BUFFER_DESC bd2; 57 ZeroMemory(&bd2, sizeof(bd2)); 58 bd2.Usage = D3D11_USAGE_DEFAULT; 59 bd2.ByteWidth = sizeof(constantBuffer); 60 bd2.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 61 bd2.CPUAccessFlags = 0; 62 hr = device->CreateBuffer(&bd2, NULL, &m_constantBuffer); 63 if (FAILED(hr)) 64 { 65 return false; 66 } 67 68 69 D3D11_SAMPLER_DESC sampDesc; 70 ZeroMemory(&sampDesc, sizeof(sampDesc)); 71 sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 72 sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; 73 sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; 74 sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP; 75 sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; 76 sampDesc.MinLOD = 0; 77 sampDesc.MaxLOD = D3D11_FLOAT32_MAX; 78 device->CreateSamplerState(&sampDesc, &m_samplerstate); 79 80 delete[] indices; 81 indices = 0; 82 83 return true; 84 } 85 86 87 bool modelclass::Loadmodel(LPCWSTR file) 88 { 89 ifstream fin; 90 char input; 91 92 fin.open(file); 93 if (fin.fail()) 94 { 95 return false; 96 } 97 98 fin.get(input); 99 while (input != ':') 100 { 101 fin.get(input); 102 } 103 104 fin >> m_vertexCount; 105 106 m_indexCount = m_vertexCount; 107 108 m_vertexlist = new vertex[m_vertexCount]; 109 if (!m_vertexlist) 110 { 111 return false; 112 } 113 114 fin.get(input); 115 while (input != ':') 116 { 117 fin.get(input); 118 } 119 fin.get(input); 120 fin.get(input); 121 122 for (int i = 0; i<m_vertexCount; i++) 123 { 124 fin >> m_vertexlist[i].pos.x >> m_vertexlist[i].pos.y >> m_vertexlist[i].pos.z; 125 fin >> m_vertexlist[i].tex.x >> m_vertexlist[i].tex.y; 126 } 127 128 fin.close(); 129 return true; 130 } 131 132 133 bool modelclass::Loadtexture(LPCWSTR file,ID3D11Device* device) 134 { 135 D3DX11CreateShaderResourceViewFromFile(device, file, NULL, NULL, &m_Texture, NULL); 136 return true; 137 } 138 139 140 void modelclass::Render(ID3D11DeviceContext* context, XMMATRIX& viewmatrix, XMMATRIX& pro, D3D11_PRIMITIVE_TOPOLOGY geometry, 141 ID3D11VertexShader* vertexshader,ID3D11PixelShader* pixelshader) 142 { 143 UINT stride = sizeof(vertex); 144 UINT offset = 0; 145 context->IASetVertexBuffers(0,1,&m_vertexBuffer,&stride,&offset); 146 context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R16_UINT, 0); 147 context->IASetPrimitiveTopology(geometry); 148 149 constantBuffer cb; 150 XMMATRIX worldmatrix = m_worldMatrix; 151 XMMATRIX promatrix = pro; 152 cb.world = XMMatrixTranspose(worldmatrix); 153 cb.view = XMMatrixTranspose(viewmatrix); 154 cb.pro = XMMatrixTranspose(promatrix); 155 156 context->UpdateSubresource(m_constantBuffer, 0, NULL, &cb, 0, 0); 157 158 context->VSSetShader(vertexshader, NULL, 0); 159 context->VSSetConstantBuffers(0, 1, &m_constantBuffer); 160 context->PSSetShader(pixelshader, NULL, 0); 161 162 context->PSSetShaderResources(0, 1, &m_Texture); 163 context->PSSetSamplers(0, 1, &m_samplerstate); 164 context->DrawIndexed(m_vertexCount, 0, 0); 165 } 166 167 168 void modelclass::Setposition(float x, float y, float z) 169 { 170 m_worldMatrix = XMMatrixTranslation(x, y, z); 171 } 172 173 174 void modelclass::RotationAxis(XMVECTOR axis, float angle) 175 { 176 m_worldMatrix *= XMMatrixRotationAxis(axis, angle); 177 } 178 179 180 void modelclass::Shutdown() 181 { 182 if (m_samplerstate) 183 { 184 m_samplerstate->Release(); 185 } 186 if (m_constantBuffer) 187 { 188 m_constantBuffer->Release(); 189 } 190 if (m_indexBuffer) 191 { 192 m_indexBuffer->Release(); 193 } 194 if (m_vertexBuffer) 195 { 196 m_vertexBuffer->Release(); 197 } 198 if (m_Texture) 199 { 200 m_Texture->Release(); 201 } 202 if (m_vertexlist) 203 { 204 delete[] m_vertexlist; 205 m_vertexlist = 0; 206 } 207 }
initialize():
- 调用私有方法加载模型和纹理。加载完模型后,顶点列表,顶点个数已经有值了;加载完纹理后,纹理资源视图也有值了。
- 填充顶点缓存描述数据结构,将顶点列表填充到源数据数据结构的pSysmem字段,然后根据顶点描述数据结构和源数据数据结构创建顶点缓存
- for循环填充索引,填充索引缓存描述数据结构,填充源数据数据结构,创建索引缓存
- 填充常量缓存描述数据结构,并创建常量缓存
- 填充取样器描述数据结构,并创建取样器状态
私有方法Loadmodel():
从磁盘读取一个文件,该文件包含顶点信息,顶点个数该文件如下
Vertex Count: 6 Data: -1.0 -1.0 0.0 0.0 1.0 -1.0 1.0 0.0 0.0 0.0 1.0 -1.0 0.0 1.0 1.0 -1.0 1.0 0.0 0.0 0.0 1.0 1.0 0.0 1.0 0.0 1.0 -1.0 0.0 1.0 1.0
这是一个txt文件,有6个顶点,每个顶点有3个位置坐标信息和2个纹理坐标信息。
这个方法很简单,就不多做叙述了。
Render():
- 设置创建好的顶点缓存
- 设置创建好的索引缓存
- 设置图形绘制方式
- 将世界转换矩阵,观察矩阵,投影矩阵填充在常量缓存里的各个字段中,并更新常量缓存
- 设置顶点着色器
- 设置常量缓存
- 设置像素着色器
- 设置纹理源
- 设置取样器的取样方式
- 绘制各个顶点
Setposition(),RotationAxis():
这两个方法只是作用于世界转换矩阵,没什么好说的,他们就是用来将模型翻转或平移的