295 lines
6.4 KiB
C++
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} |