Files
GP1-DirectX/project/src/Mesh.cpp
2025-01-14 02:26:26 +01:00

148 lines
4.8 KiB
C++

#include <cassert>
#include <utility>
#include "pch.h"
#include "Mesh.h"
#include "Effects/Effect.h"
Mesh::Mesh(ID3D11Device *devicePtr, const std::vector<VertexIn> &verticesIn, const std::vector<Uint32> &indices, std::shared_ptr<Material> material, BaseEffect* effectPtr) :
m_EffectPtr(effectPtr),
m_InputLayoutPtr(nullptr),
m_VertexBufferPtr(nullptr),
m_IndexBufferPtr(nullptr),
m_VerticesIn(verticesIn),
m_Indices(indices),
m_IndicesCount(static_cast<UINT>(m_Indices.size())),
m_Material(std::move(material)) {
HRESULT result;
D3D11_BUFFER_DESC bufferDesc{};
D3D11_SUBRESOURCE_DATA subresourceData{};
m_EffectPtr->SetMaterial(m_Material.get());
//Create vertex layout
static constexpr uint32_t vertexElementCount{4};
D3D11_INPUT_ELEMENT_DESC vertexDesc[vertexElementCount]{};
vertexDesc[0].SemanticName = "POSITION";
vertexDesc[0].Format = DXGI_FORMAT_R32G32B32_FLOAT;
vertexDesc[0].AlignedByteOffset = 0;
vertexDesc[0].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
vertexDesc[1].SemanticName = "TEXCOORD";
vertexDesc[1].Format = DXGI_FORMAT_R32G32_FLOAT;
vertexDesc[1].AlignedByteOffset = offsetof(VertexIn, uv);
vertexDesc[1].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
vertexDesc[2].SemanticName = "NORMAL";
vertexDesc[2].Format = DXGI_FORMAT_R32G32B32_FLOAT;
vertexDesc[2].AlignedByteOffset = offsetof(VertexIn, normal);
vertexDesc[2].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
vertexDesc[3].SemanticName = "TANGENT";
vertexDesc[3].Format = DXGI_FORMAT_R32G32B32_FLOAT;
vertexDesc[3].AlignedByteOffset = offsetof(VertexIn, tangent);
vertexDesc[3].InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
//Create input layout
D3DX11_PASS_DESC passDesc{};
ID3DX11EffectTechnique *techniquePtr = m_EffectPtr->GetTechniquePtr();
techniquePtr->GetPassByIndex(0)->GetDesc(&passDesc);
result = devicePtr->CreateInputLayout(
vertexDesc,
vertexElementCount,
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
&m_InputLayoutPtr);
assert(result == S_OK && "Creating input layout failed");
//Create vertex buffer
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
bufferDesc.ByteWidth = sizeof(VertexIn) * static_cast<uint32_t>(verticesIn.size());
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
subresourceData.pSysMem = verticesIn.data();
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_VertexBufferPtr);
assert(result == S_OK && "Creating vertex buffer failed");
//Create index buffer
bufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
bufferDesc.ByteWidth = sizeof(uint32_t) * m_IndicesCount;
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
subresourceData.pSysMem = m_Indices.data();
result = devicePtr->CreateBuffer(&bufferDesc, &subresourceData, &m_IndexBufferPtr);
assert(result == S_OK && "Creating index buffer failed");
}
Mesh::~Mesh() {
m_InputLayoutPtr->Release();
m_InputLayoutPtr = nullptr;
m_VertexBufferPtr->Release();
m_VertexBufferPtr = nullptr;
m_IndexBufferPtr->Release();
m_IndexBufferPtr = nullptr;
delete m_EffectPtr;
m_EffectPtr = nullptr;
}
void Mesh::Render(ID3D11DeviceContext *deviceContextPtr, const Matrix &worldViewProj) const {
m_EffectPtr->SetWorldViewProjMatrix(worldViewProj);
m_EffectPtr->SetWorldMatrix(m_WorldMatrix);
deviceContextPtr->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
deviceContextPtr->IASetInputLayout(m_InputLayoutPtr);
constexpr UINT stride = sizeof(VertexIn);
constexpr UINT offset = 0;
deviceContextPtr->IASetVertexBuffers(0, 1, &m_VertexBufferPtr, &stride, &offset);
deviceContextPtr->IASetIndexBuffer(m_IndexBufferPtr, DXGI_FORMAT_R32_UINT, 0);
D3DX11_TECHNIQUE_DESC techniqueDesc{};
m_EffectPtr->GetTechniquePtr()->GetDesc(&techniqueDesc);
for (UINT p{}; p < techniqueDesc.Passes; p++) {
m_EffectPtr->GetTechniquePtr()->GetPassByIndex(p)->Apply(0, deviceContextPtr);
deviceContextPtr->DrawIndexed(m_IndicesCount, 0, 0);
}
}
void Mesh::NextSamplingState() {
m_EffectPtr->NextSamplingState();
}
void Mesh::SetCameraPos(const Vector3 &pos) const {
m_EffectPtr->SetCameraPos(pos);
}
void Mesh::SetWorldMatrix(const Matrix &matrix) {
m_WorldMatrix = matrix;
}
void Mesh::ToggleNormals() {
m_EffectPtr->ToggleNormals();
}
void Mesh::SetMaterial(Material *pMaterial) {
m_Material.reset(pMaterial);
m_EffectPtr->SetMaterial(pMaterial);
}
void Mesh::CycleCullMode() {
m_EffectPtr->NextCullMode();
}
BaseEffect *Mesh::GetEffect() {
return m_EffectPtr;
}