207 lines
6.1 KiB
C++
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;
|
|
}
|
|
}
|