1#include "model_class.h"
4model_class::model_class()
11 m_Textures.diffuse.clear();
12 m_Textures.normal.clear();
13 m_Textures.specular.clear();
14 m_Textures.alpha.clear();
15 m_Textures.diffusePaths.clear();
16 m_Textures.normalPaths.clear();
17 m_Textures.specularPaths.clear();
18 m_Textures.alphaPaths.clear();
21model_class::~model_class()
28bool model_class::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext,
char* modelFilename,
const TextureContainer& textures) {
30 bool result = Initialize(device, deviceContext, modelFilename);
35 m_Textures = textures;
40bool model_class::Initialize(ID3D11Device* device, ID3D11DeviceContext* deviceContext,
char* modelFilename) {
45 result = LoadModel(modelFilename);
47 Logger::Get().
Log(
"Failed to load model data", __FILE__, __LINE__, Logger::LogLevel::Error);
52 CalculateModelVectors();
55 result = InitializeBuffers(device);
57 Logger::Get().
Log(
"Failed to initialize buffers", __FILE__, __LINE__, Logger::LogLevel::Error);
64void model_class::Shutdown()
79void model_class::Render(ID3D11DeviceContext* deviceContext)
82 RenderBuffers(deviceContext);
88int model_class::GetIndexCount()
93ID3D11ShaderResourceView* model_class::GetTexture(TextureType type,
int index)
const {
94 return m_Textures.GetTexture(type, index);
97bool model_class::InitializeBuffers(ID3D11Device* device)
100 VertexType* vertices;
101 unsigned long* indices;
102 D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
103 D3D11_SUBRESOURCE_DATA vertexData, indexData;
108 vertices =
new VertexType[m_vertexCount];
111 indices =
new unsigned long[m_indexCount];
114 for (i = 0; i < m_vertexCount; i++)
116 vertices[i].position = XMFLOAT3(m_model[i].x, m_model[i].y, m_model[i].z);
117 vertices[i].texture = XMFLOAT2(m_model[i].tu, m_model[i].tv);
118 vertices[i].normal = XMFLOAT3(m_model[i].nx, m_model[i].ny, m_model[i].nz);
119 vertices[i].tangent = XMFLOAT3(m_model[i].tx, m_model[i].ty, m_model[i].tz);
120 vertices[i].binormal = XMFLOAT3(m_model[i].bx, m_model[i].by, m_model[i].bz);
126 vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
127 vertexBufferDesc.ByteWidth =
sizeof(VertexType) * m_vertexCount;
128 vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
129 vertexBufferDesc.CPUAccessFlags = 0;
130 vertexBufferDesc.MiscFlags = 0;
131 vertexBufferDesc.StructureByteStride = 0;
134 vertexData.pSysMem = vertices;
135 vertexData.SysMemPitch = 0;
136 vertexData.SysMemSlicePitch = 0;
139 result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer);
142 Logger::Get().
Log(
"Failed to create vertex buffer", __FILE__, __LINE__, Logger::LogLevel::Error);
147 indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
148 indexBufferDesc.ByteWidth =
sizeof(
unsigned long) * m_indexCount;
149 indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
150 indexBufferDesc.CPUAccessFlags = 0;
151 indexBufferDesc.MiscFlags = 0;
152 indexBufferDesc.StructureByteStride = 0;
155 indexData.pSysMem = indices;
156 indexData.SysMemPitch = 0;
157 indexData.SysMemSlicePitch = 0;
160 result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer);
163 Logger::Get().
Log(
"Failed to create index buffer", __FILE__, __LINE__, Logger::LogLevel::Error);
177void model_class::ShutdownBuffers()
179 if (m_indexBuffer) { m_indexBuffer->Release(); m_indexBuffer =
nullptr; }
180 if (m_vertexBuffer) { m_vertexBuffer->Release(); m_vertexBuffer =
nullptr; }
183void model_class::RenderBuffers(ID3D11DeviceContext* deviceContext)
190 stride =
sizeof(VertexType);
194 deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
197 deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
200 deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
205void model_class::ReleaseTextures()
209 m_Textures.ReleaseAll();
212bool model_class::LoadModel(
char* filename)
215 std::string fileStr(filename);
216 std::string extension = fileStr.substr(fileStr.find_last_of(
".") + 1);
218 if (extension ==
"obj")
221 return LoadObjModel(filename);
223 else if (extension ==
"txt")
226 return LoadTxtModel(filename);
230 Logger::Get().
Log(
"Unsupported file format", __FILE__, __LINE__, Logger::LogLevel::Error);
235bool model_class::LoadObjModel(
char* filename)
238 std::ifstream fin(filename, std::ios::in | std::ios::binary);
241 Logger::Get().
Log(
"Échec d'ouverture du fichier modèle", __FILE__, __LINE__, Logger::LogLevel::Error);
246 fin.seekg(0, std::ios::end);
247 const size_t fileSize = fin.tellg();
248 fin.seekg(0, std::ios::beg);
250 std::string fileContent;
251 fileContent.resize(fileSize);
252 fin.read(&fileContent[0], fileSize);
256 const size_t estimatedVertices = fileSize / 150;
257 std::vector<XMFLOAT3> temp_positions;
258 std::vector<XMFLOAT2> temp_texcoords;
259 std::vector<XMFLOAT3> temp_normals;
260 std::vector<ModelType> temp_model;
262 temp_positions.reserve(estimatedVertices);
263 temp_texcoords.reserve(estimatedVertices);
264 temp_normals.reserve(estimatedVertices);
265 temp_model.reserve(estimatedVertices * 3);
268 std::istringstream iss(fileContent);
271 while (std::getline(iss, line))
273 if (line.empty() || line[0] ==
'#')
continue;
281 sscanf_s(line.c_str() + 2,
"%f %f %f", &pos.x, &pos.y, &pos.z);
282 temp_positions.push_back(pos);
284 else if (line[1] ==
't')
287 sscanf_s(line.c_str() + 3,
"%f %f", &tex.x, &tex.y);
288 temp_texcoords.push_back(tex);
290 else if (line[1] ==
'n')
293 sscanf_s(line.c_str() + 3,
"%f %f %f", &norm.x, &norm.y, &norm.z);
294 temp_normals.push_back(norm);
297 else if (line[0] ==
'f')
299 int posIndex[3], texIndex[3], normIndex[3];
300 const char* linePtr = line.c_str() + 2;
302 for (
int i = 0; i < 3; i++)
305 sscanf_s(linePtr,
"%d/%d/%d", &posIndex[i], &texIndex[i], &normIndex[i]);
308 while (*linePtr && *linePtr !=
' ') linePtr++;
309 while (*linePtr ==
' ') linePtr++;
311 if (posIndex[i] < 0) posIndex[i] += temp_positions.size() + 1;
312 if (texIndex[i] < 0) texIndex[i] += temp_texcoords.size() + 1;
313 if (normIndex[i] < 0) normIndex[i] += temp_normals.size() + 1;
316 for (
int i = 0; i < 3; i++)
319 vertex.x = temp_positions[posIndex[i] - 1].x;
320 vertex.y = temp_positions[posIndex[i] - 1].y;
321 vertex.z = temp_positions[posIndex[i] - 1].z;
322 vertex.tu = temp_texcoords[texIndex[i] - 1].x;
323 vertex.tv = temp_texcoords[texIndex[i] - 1].y;
324 vertex.nx = temp_normals[normIndex[i] - 1].x;
325 vertex.ny = temp_normals[normIndex[i] - 1].y;
326 vertex.nz = temp_normals[normIndex[i] - 1].z;
327 temp_model.push_back(vertex);
333 m_vertexCount = temp_model.size();
334 m_indexCount = temp_model.size();
335 m_model =
new ModelType[m_vertexCount];
336 std::memcpy(m_model, temp_model.data(), m_vertexCount *
sizeof(ModelType));
341bool model_class::LoadTxtModel(
char* filename)
354 Logger::Get().
Log(
"Failed to open model file", __FILE__, __LINE__, Logger::LogLevel::Error);
366 fin >> m_vertexCount;
369 m_indexCount = m_vertexCount;
372 m_model =
new ModelType[m_vertexCount];
384 for (i = 0; i < m_vertexCount; i++)
386 fin >> m_model[i].x >> m_model[i].y >> m_model[i].z;
387 fin >> m_model[i].tu >> m_model[i].tv;
388 fin >> m_model[i].nx >> m_model[i].ny >> m_model[i].nz;
397void model_class::CalculateModelVectors()
399 int faceCount, i, index;
400 TempVertexType vertex1, vertex2, vertex3;
401 VectorType tangent, binormal;
405 faceCount = m_vertexCount / 3;
411 for (i = 0; i < faceCount; i++)
414 vertex1.x = m_model[index].x;
415 vertex1.y = m_model[index].y;
416 vertex1.z = m_model[index].z;
417 vertex1.tu = m_model[index].tu;
418 vertex1.tv = m_model[index].tv;
421 vertex2.x = m_model[index].x;
422 vertex2.y = m_model[index].y;
423 vertex2.z = m_model[index].z;
424 vertex2.tu = m_model[index].tu;
425 vertex2.tv = m_model[index].tv;
428 vertex3.x = m_model[index].x;
429 vertex3.y = m_model[index].y;
430 vertex3.z = m_model[index].z;
431 vertex3.tu = m_model[index].tu;
432 vertex3.tv = m_model[index].tv;
436 CalculateTangentBinormal(vertex1, vertex2, vertex3, tangent, binormal);
439 m_model[index - 1].tx = tangent.x;
440 m_model[index - 1].ty = tangent.y;
441 m_model[index - 1].tz = tangent.z;
442 m_model[index - 1].bx = binormal.x;
443 m_model[index - 1].by = binormal.y;
444 m_model[index - 1].bz = binormal.z;
446 m_model[index - 2].tx = tangent.x;
447 m_model[index - 2].ty = tangent.y;
448 m_model[index - 2].tz = tangent.z;
449 m_model[index - 2].bx = binormal.x;
450 m_model[index - 2].by = binormal.y;
451 m_model[index - 2].bz = binormal.z;
453 m_model[index - 3].tx = tangent.x;
454 m_model[index - 3].ty = tangent.y;
455 m_model[index - 3].tz = tangent.z;
456 m_model[index - 3].bx = binormal.x;
457 m_model[index - 3].by = binormal.y;
458 m_model[index - 3].bz = binormal.z;
462void model_class::CalculateTangentBinormal(TempVertexType vertex1, TempVertexType vertex2, TempVertexType vertex3, VectorType& tangent, VectorType& binormal)
465 float vector1[3], vector2[3];
466 float tuVector[2], tvVector[2];
472 vector1[0] = vertex2.x - vertex1.x;
473 vector1[1] = vertex2.y - vertex1.y;
474 vector1[2] = vertex2.z - vertex1.z;
476 vector2[0] = vertex3.x - vertex1.x;
477 vector2[1] = vertex3.y - vertex1.y;
478 vector2[2] = vertex3.z - vertex1.z;
481 tuVector[0] = vertex2.tu - vertex1.tu;
482 tvVector[0] = vertex2.tv - vertex1.tv;
484 tuVector[1] = vertex3.tu - vertex1.tu;
485 tvVector[1] = vertex3.tv - vertex1.tv;
488 den = 1.0f / (tuVector[0] * tvVector[1] - tuVector[1] * tvVector[0]);
491 tangent.x = (tvVector[1] * vector1[0] - tvVector[0] * vector2[0]) * den;
492 tangent.y = (tvVector[1] * vector1[1] - tvVector[0] * vector2[1]) * den;
493 tangent.z = (tvVector[1] * vector1[2] - tvVector[0] * vector2[2]) * den;
495 binormal.x = (tuVector[0] * vector2[0] - tuVector[1] * vector1[0]) * den;
496 binormal.y = (tuVector[0] * vector2[1] - tuVector[1] * vector1[1]) * den;
497 binormal.z = (tuVector[0] * vector2[2] - tuVector[1] * vector1[2]) * den;
500 length = sqrt((tangent.x * tangent.x) + (tangent.y * tangent.y) + (tangent.z * tangent.z));
503 tangent.x = tangent.x / length;
504 tangent.y = tangent.y / length;
505 tangent.z = tangent.z / length;
508 length = sqrt((binormal.x * binormal.x) + (binormal.y * binormal.y) + (binormal.z * binormal.z));
511 binormal.x = binormal.x / length;
512 binormal.y = binormal.y / length;
513 binormal.z = binormal.z / length;
516void model_class::ReleaseModel()
526bool model_class::PreloadTextures(ID3D11Device* device, ID3D11DeviceContext* deviceContext,
TextureContainer& textureContainer)
531 for (
const auto& texturePath : textureContainer.diffusePaths)
533 ID3D11ShaderResourceView* texture =
nullptr;
534 hResult = DirectX::CreateWICTextureFromFile(device, deviceContext, texturePath.c_str(),
nullptr, &texture);
537 Logger::Get().
Log(
"Échec du chargement de la texture diffuse: " + std::string(texturePath.begin(), texturePath.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
540 textureContainer.diffuse.push_back(texture);
544 for (
const auto& texturePath : textureContainer.normalPaths)
546 ID3D11ShaderResourceView* texture =
nullptr;
547 hResult = DirectX::CreateWICTextureFromFile(device, deviceContext, texturePath.c_str(),
nullptr, &texture);
550 Logger::Get().
Log(
"Échec du chargement de la texture normale: " + std::string(texturePath.begin(), texturePath.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
553 textureContainer.normal.push_back(texture);
557 for (
const auto& texturePath : textureContainer.specularPaths)
559 ID3D11ShaderResourceView* texture =
nullptr;
560 hResult = DirectX::CreateWICTextureFromFile(device, deviceContext, texturePath.c_str(),
nullptr, &texture);
563 Logger::Get().
Log(
"Échec du chargement de la texture spéculaire: " + std::string(texturePath.begin(), texturePath.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
566 textureContainer.specular.push_back(texture);
570 for (
const auto& texturePath : textureContainer.alphaPaths)
572 ID3D11ShaderResourceView* texture =
nullptr;
573 hResult = DirectX::CreateWICTextureFromFile(device, deviceContext, texturePath.c_str(),
nullptr, &texture);
576 Logger::Get().
Log(
"Échec du chargement de la texture alpha: " + std::string(texturePath.begin(), texturePath.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
579 textureContainer.alpha.push_back(texture);
585bool model_class::ChangeTexture(ID3D11Device* device, ID3D11DeviceContext* deviceContext, std::wstring filename, TextureType type,
int index) {
586 Logger::Get().
Log(
"Changing texture", __FILE__, __LINE__, Logger::LogLevel::Initialize);
589 ID3D11ShaderResourceView* newTexture =
nullptr;
592 result = DirectX::CreateWICTextureFromFile(device, deviceContext, filename.c_str(),
nullptr, &newTexture);
593 if (FAILED(result)) {
594 Logger::Get().
Log(
"Failed to load texture: " + std::string(filename.begin(), filename.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
599 auto& textureVector = m_Textures.Get(type);
602 if (index >= textureVector.size()) {
603 textureVector.resize(index + 1,
nullptr);
607 if (textureVector[index]) {
608 textureVector[index]->Release();
612 textureVector[index] = newTexture;
616 case TextureType::Diffuse:
617 if (index >= m_Textures.diffusePaths.size()) {
618 m_Textures.diffusePaths.resize(index + 1, L
"");
620 m_Textures.diffusePaths[index] = filename;
622 case TextureType::Normal:
623 if (index >= m_Textures.normalPaths.size()) {
624 m_Textures.normalPaths.resize(index + 1, L
"");
626 m_Textures.normalPaths[index] = filename;
628 case TextureType::Specular:
629 if (index >= m_Textures.specularPaths.size()) {
630 m_Textures.specularPaths.resize(index + 1, L
"");
632 m_Textures.specularPaths[index] = filename;
634 case TextureType::Alpha:
635 if (index >= m_Textures.alphaPaths.size()) {
636 m_Textures.alphaPaths.resize(index + 1, L
"");
638 m_Textures.alphaPaths[index] = filename;
642 Logger::Get().
Log(
"Texture changed successfully", __FILE__, __LINE__, Logger::LogLevel::Initialize);
646bool model_class::AddTexture(ID3D11Device* device, ID3D11DeviceContext* deviceContext, std::wstring filename, TextureType type) {
647 Logger::Get().
Log(
"Adding texture", __FILE__, __LINE__, Logger::LogLevel::Initialize);
650 ID3D11ShaderResourceView* newTexture =
nullptr;
653 result = DirectX::CreateWICTextureFromFile(device, deviceContext, filename.c_str(),
nullptr, &newTexture);
654 if (FAILED(result)) {
655 Logger::Get().
Log(
"Failed to load texture: " + std::string(filename.begin(), filename.end()), __FILE__, __LINE__, Logger::LogLevel::Error);
660 auto& textureVector = m_Textures.Get(type);
661 textureVector.push_back(newTexture);
665 case TextureType::Diffuse:
666 m_Textures.diffusePaths.push_back(filename);
668 case TextureType::Normal:
669 m_Textures.normalPaths.push_back(filename);
671 case TextureType::Specular:
672 m_Textures.specularPaths.push_back(filename);
674 case TextureType::Alpha:
675 m_Textures.alphaPaths.push_back(filename);
679 Logger::Get().
Log(
"Texture added successfully", __FILE__, __LINE__, Logger::LogLevel::Initialize);
683bool model_class::AddTexture(ID3D11ShaderResourceView* texture, TextureType type) {
685 Logger::Get().
Log(
"Cannot add null texture", __FILE__, __LINE__, Logger::LogLevel::Error);
690 auto& textureVector = m_Textures.Get(type);
691 textureVector.push_back(texture);
695 case TextureType::Diffuse:
696 m_Textures.diffusePaths.push_back(L
"[texture préchargée]");
698 case TextureType::Normal:
699 m_Textures.normalPaths.push_back(L
"[texture préchargée]");
701 case TextureType::Specular:
702 m_Textures.specularPaths.push_back(L
"[texture préchargée]");
704 case TextureType::Alpha:
705 m_Textures.alphaPaths.push_back(L
"[texture préchargée]");
void Log(const std::string &message, const std::string &fileName, int lineNumber, LogLevel level=LogLevel::Info)