Files
Nuake-custom/Nuake/src/Rendering/Mesh/SkinnedMesh.cpp
2024-09-09 20:55:51 -04:00

207 lines
6.1 KiB
C++

#include "SkinnedMesh.h"
#include "src/Core/Maths.h"
#include "src/Rendering/Textures/Material.h"
#include "src/Rendering/Textures/MaterialManager.h"
#include "src/Rendering/Renderer.h"
#include "src/Rendering/Shaders/Shader.h"
#include "src/Rendering/Vertex.h"
#include "src/Rendering/Buffers/VertexBuffer.h"
#include "src/Rendering/Buffers/VertexArray.h"
#include "src/Rendering/Buffers/VertexBufferLayout.h"
#include <future>
namespace Nuake
{
void SkinnedMesh::AddSurface(std::vector<SkinnedVertex> vertices, std::vector<uint32_t> indices, std::vector<Bone> bones)
{
m_Vertices = vertices;
m_Indices = indices;
SetupMesh();
CalculateAABB();
if (m_Material == nullptr)
{
m_Material = MaterialManager::Get()->GetMaterial("default");
}
}
std::vector<SkinnedVertex>& SkinnedMesh::GetVertices()
{
return m_Vertices;
}
std::vector<uint32_t>& SkinnedMesh::GetIndices()
{
return m_Indices;
}
Ref<Material> SkinnedMesh::GetMaterial() const
{
return m_Material;
}
void SkinnedMesh::SetMaterial(Ref<Material> material)
{
m_Material = material;
MaterialManager::Get()->RegisterMaterial(material);
}
void SkinnedMesh::CalculateAABB()
{
float minX = 0.0f;
float minY = 0.0f;
float minZ = 0.0f;
float maxX = 0.0f;
float maxY = 0.0f;
float maxZ = 0.0f;
for (const SkinnedVertex& v : m_Vertices)
{
minX = v.position.x < minX ? v.position.x : minX;
minY = v.position.y < minY ? v.position.y : minY;
minZ = v.position.z < minZ ? v.position.z : minZ;
maxX = v.position.x > maxX ? v.position.x : maxX;
maxY = v.position.y > maxY ? v.position.y : maxY;
maxZ = v.position.z > maxZ ? v.position.z : maxZ;
}
m_AABB = AABB(Vector3(minX, minY, minZ), Vector3(maxX, maxY, maxZ));
}
void SkinnedMesh::SetupMesh()
{
m_VertexArray = CreateScope<VertexArray>();
m_VertexArray->Bind();
m_VertexBuffer = CreateScope<VertexBuffer>(m_Vertices.data(), m_Vertices.size() * sizeof(SkinnedVertex));
m_ElementBuffer = CreateScope<VertexBuffer>(m_Indices.data(), m_Indices.size() * sizeof(unsigned int), RendererEnum::ELEMENT_ARRAY_BUFFER);
VertexBufferLayout bufferLayout = VertexBufferLayout();
bufferLayout.Push<float>(3); // Position
bufferLayout.Push<float>(2); // UV
bufferLayout.Push<float>(3); // Normal
bufferLayout.Push<float>(3); // Tangent
bufferLayout.Push<float>(3); // Bitangent
bufferLayout.Push<int>(4); // BoneIds
bufferLayout.Push<float>(4); // Weights
m_VertexArray->AddBuffer(*m_VertexBuffer, bufferLayout);
m_VertexArray->Unbind();
}
void SkinnedMesh::Bind() const
{
m_VertexArray->Bind();
}
void SkinnedMesh::Draw(Shader* shader, bool bindMaterial)
{
if (bindMaterial)
m_Material->Bind(shader);
m_VertexArray->Bind();
RenderCommand::DrawElements(RendererEnum::TRIANGLES, (int)m_Indices.size(), RendererEnum::UINT, 0);
}
void SkinnedMesh::DebugDraw()
{
Renderer::m_DebugShader->Bind();
Renderer::m_DebugShader->SetUniform("u_Color", 1.0f, 0.0f, 0.0f, 1.f);
m_VertexArray->Bind();
RenderCommand::DrawElements(RendererEnum::TRIANGLES, (int)m_Indices.size(), RendererEnum::UINT, 0);
}
json SkinnedMesh::Serialize()
{
BEGIN_SERIALIZE();
j["Material"] = m_Material->Serialize();
j["Indices"] = m_Indices;
json v;
for (uint32_t i = 0; i < m_Vertices.size(); i++)
{
v["Position"]["x"] = m_Vertices[i].position.x;
v["Position"]["y"] = m_Vertices[i].position.y;
v["Position"]["z"] = m_Vertices[i].position.z;
v["UV"]["x"] = m_Vertices[i].uv.x;
v["UV"]["y"] = m_Vertices[i].uv.y;
v["Normal"]["x"] = m_Vertices[i].normal.x;
v["Normal"]["y"] = m_Vertices[i].normal.y;
v["Normal"]["z"] = m_Vertices[i].normal.z;
v["Tangent"]["x"] = m_Vertices[i].tangent.x;
v["Tangent"]["y"] = m_Vertices[i].tangent.y;
v["Tangent"]["z"] = m_Vertices[i].tangent.z;
v["Bitangent"]["x"] = m_Vertices[i].bitangent.x;
v["Bitangent"]["y"] = m_Vertices[i].bitangent.y;
v["Bitangent"]["z"] = m_Vertices[i].bitangent.z;
for (uint32_t b = 0; b < MAX_BONE_INFLUENCE; b++)
{
v["Weight"][b] = m_Vertices[i].weights[b];
v["BoneIDs"][b] = m_Vertices[i].boneIDs[b];
}
j["Vertices"][i] = v;
}
END_SERIALIZE();
}
bool SkinnedMesh::Deserialize(const json& j)
{
m_Material = CreateRef<Material>();
m_Material->Deserialize(j["Material"]);
m_Indices.reserve(j["Indices"].size());
for (auto& i : j["Indices"])
{
m_Indices.push_back(i);
}
std::vector<SkinnedVertex> vertices;
std::async(std::launch::async, [&]()
{
for (auto& v : j["Vertices"])
{
SkinnedVertex vertex;
try {
DESERIALIZE_VEC2(v["UV"], vertex.uv)
}
catch (std::exception& /*e*/) {
vertex.uv = { 0.0, 0.0 };
}
DESERIALIZE_VEC3(v["Position"], vertex.position)
DESERIALIZE_VEC3(v["Normal"], vertex.normal)
DESERIALIZE_VEC3(v["Tangent"], vertex.tangent)
DESERIALIZE_VEC3(v["Bitangent"], vertex.bitangent)
for (uint32_t i = 0; i < MAX_BONE_INFLUENCE; i++)
{
vertex.weights[i] = v["Weight"][i];
vertex.boneIDs[i] = v["boneIDs"][i];
}
vertices.push_back(vertex);
}
}
);
m_Vertices = vertices;
SetupMesh();
return true;
}
}