Files
EHS/src/IO/Model/Model.cpp
2023-12-17 15:00:08 -08:00

295 lines
6.4 KiB
C++

#include "IO/Model/Model.h"
namespace lwe
{
Model::Model()
{
AddType("Model");
}
Model::Model(const Str_8& filePath)
{
AddType("Model");
File file(filePath, Mode::READ, Disposition::OPEN);
hashId = file.GetName().Hash_64();
id = file.GetName();
if (file.GetExtension() == "ehm")
{
FromEHM(file);
}
}
Model::Model(Str_8 id, Array<Mesh> meshes, Bone skeleton, Array<Animation> animations)
: Resource(std::move(id)), meshes(std::move(meshes)), skeleton(std::move(skeleton)),
animations(std::move(animations))
{
AddType("Model");
}
Model::Model(Str_8 id, Array<Mesh> meshes, Bone skeleton)
: Resource(std::move(id)), meshes(std::move(meshes)), skeleton(std::move(skeleton))
{
AddType("Model");
}
Model::Model(Str_8 id, Array<Mesh> meshes)
: Resource(std::move(id)), meshes(std::move(meshes))
{
AddType("Model");
}
Model::Model(Model&& model) noexcept
: Resource(std::move(model)), meshes(std::move(model.meshes)),
skeleton(std::move(model.skeleton)), animations(std::move(model.animations))
{
}
Model& Model::operator=(Model&& model) noexcept
{
if (this == &model)
return *this;
hashId = model.hashId;
id = std::move(model.id);
meshes = std::move(model.meshes);
skeleton = std::move(model.skeleton);
animations = std::move(model.animations);
model.hashId = 0;
return *this;
}
bool Model::UploadToGpu(GpuCmdBuffer* cmdBuffer)
{
for (UInt_64 i = 0; i < meshes.Size(); ++i)
if (!meshes[i].UploadToGpu(cmdBuffer))
return false;
return true;
}
bool Model::PostGpuUpload()
{
bool result = true;
for (UInt_64 i = 0; i < meshes.Size(); ++i)
if (!meshes[i].PostGpuUpload())
result = false;
return result;
}
bool Model::ReleaseFromGpu()
{
bool result = true;
for (UInt_64 i = 0; i < meshes.Size(); ++i)
if (!meshes[i].ReleaseFromGpu())
result = false;
return result;
}
bool Model::IsUploaded() const
{
return meshes[0].IsUploaded();
}
void Model::Draw(GpuCmdBuffer* cmdBuffer, const UInt_32 instances)
{
for (UInt_64 i = 0; i < meshes.Size(); ++i)
{
meshes[i].Bind(cmdBuffer);
meshes[i].Draw(cmdBuffer, instances);
}
}
Array<Mesh> Model::GetMeshes() const
{
return meshes;
}
Array<Mesh>& Model::GetMeshes()
{
return meshes;
}
Mesh* Model::GetMesh(const UInt_64 hashId)
{
for (UInt_64 i = 0; i < meshes.Size(); ++i)
if (meshes[i].GetHashId() == hashId)
return &meshes[i];
return nullptr;
}
Mesh* Model::GetMesh(const Str_8& id)
{
return GetMesh(id.Hash_64());
}
Bone Model::GetSkeleton() const
{
return skeleton;
}
Bone& Model::GetSkeleton()
{
return skeleton;
}
Animation* Model::GetAnimation(const UInt_64 hashId)
{
for (UInt_64 i = 0; i < animations.Size(); ++i)
if (animations[i].GetHashId() == hashId)
return &animations[i];
return nullptr;
}
Array<Animation> Model::GetAnimations() const
{
return animations;
}
Array<Animation>& Model::GetAnimations()
{
return animations;
}
void Model::Calculate()
{
for (UInt_64 i = 0; i < meshes.Size(); ++i)
meshes[i].Calculate();
}
void Model::Export(const Str_8& filePath, const ModelEncoding encoding)
{
File file(filePath, Mode::WRITE, Disposition::OPEN_PERSISTENT);
switch (encoding)
{
case ModelEncoding::EHM:
{
ToEHM(file);
break;
}
}
}
void Model::ToEHM(File& file)
{
Serializer<UInt_64> data(Endianness::LE);
data.WriteVersion({1, 0, 0});
data.Write<UInt_64>(meshes.Size());
for (UInt_64 i = 0; i < meshes.Size(); ++i)
{
data.WriteStr(meshes[i].GetId());
Array<Vertex_f> vertices = meshes[i].GetVertices();
data.Write<UInt_64>(vertices.Size());
for (UInt_64 v = 0; v < vertices.Size(); ++v)
{
data.WriteVec3(vertices[v].pos);
data.WriteVec3(vertices[v].normal);
data.WriteVec2(vertices[v].uv);
}
}
file.WriteSerializer_64(data);
file.Truncate(data.Size());
}
void Model::FromEHM(File& file)
{
Serializer<UInt_64> data = file.ReadSerializer_64(Endianness::LE, file.Size());
Version ver = data.ReadVersion();
if (ver != Version(1, 0, 0))
{
LWE_LOG_INT("Error", 0, "Cannot decode EHM file version " + Str_8::FromNum(ver.major) + "." +
Str_8::FromNum(ver.minor) + "." + Str_8::FromNum(ver.patch) +
", must be version 0.0.0.");
return;
}
meshes.Resize(data.Read<UInt_64>());
for (UInt_64 i = 0; i < meshes.Size(); ++i)
{
meshes[i].SetId(data.ReadStr<Char_8, UInt_64>());
meshes[i].SetParent(this);
Array<Vertex_f>& vertices = meshes[i].GetVertices();
vertices.Resize(data.Read<UInt_64>());
for (UInt_64 v = 0; v < vertices.Size(); ++v)
{
vertices[v].pos = data.ReadVec3<float>();
vertices[v].normal = data.ReadVec3<float>();
vertices[v].uv = data.ReadVec2<float>();
vertices[v].bones = data.ReadVec4<UInt_8>();
vertices[v].weights = data.ReadVec4<float>();
}
meshes[i].SetIndices(data.ReadArray<UInt_32, UInt_64>());
UInt_8 boneCount = data.Read<UInt_8>();
for (UInt_8 b = 0; b < boneCount; ++b)
{
Str_8 name = data.ReadStr<Char_8, UInt_64>();
UInt_8 parentId = data.Read<UInt_8>();
Mat4_f localBindTrans = data.ReadMat4<float>();
Mat4_f invBindTrans = data.ReadMat4<float>();
if (b == 0)
{
skeleton = {name, b, localBindTrans, invBindTrans};
}
else
{
Bone* parent = skeleton.GetBone(parentId);
if (!parent)
{
LWE_LOG_INT("Error", 0, "Invalid bone order.");
return;
}
parent->AddBone({name, b, localBindTrans, invBindTrans});
}
}
animations = Array<Animation>(data.Read<UInt_64>());
for (UInt_64 a = 0; a < animations.Size(); ++a)
{
Str_8 animId = data.ReadStr<Char_8, UInt_64>();
float duration = data.Read<float>();
animations[a] = Animation(animId, duration, data.Read<UInt_8>());
Array<AnimBone>& animated = animations[a].GetAnimated();
for (UInt_8 ba = 0; ba < (UInt_8)animated.Size(); ++ba)
{
UInt_8 boneId = data.Read<UInt_8>();
animated[ba] = AnimBone(boneId, data.Read<UInt_64>());
Array<KeyFrame>& keyFrames = animated[ba].GetKeyFrames();
for (UInt_64 kf = 0; kf < keyFrames.Size(); ++kf)
{
float num = data.Read<float>();
float timeStamp = data.Read<float>();
Vec3_f pos = data.ReadVec3<float>();
Quat_f rot = data.ReadQuat<float>();
Vec3_f scale = data.ReadVec3<float>();
keyFrames[kf] = KeyFrame(num, timeStamp, pos, rot, scale);
}
}
}
}
}
}