2022-05-21 19:58:09 +02:00

147 lines
3.7 KiB
C++

#include "stdafx.h"
#include "Model.h"
#include "Matrix.h"
namespace Assets
{
Model::Model()
: Model(0, 0, 0)
{
}
Model::Model(uint32_t SubmeshCount)
: Model(SubmeshCount, 0, 0)
{
}
Model::Model(uint32_t SubmeshCount, uint32_t BoneCount)
: Model(SubmeshCount, BoneCount, 0)
{
}
Model::Model(uint32_t SubmeshCount, uint32_t BoneCount, uint32_t MaterialCount)
: Meshes(SubmeshCount), Bones(BoneCount), Materials(MaterialCount), Name("error")
{
}
uint32_t Model::VertexCount() const
{
uint32_t Result = 0;
for (auto& Mesh : Meshes)
Result += Mesh.Vertices.Count();
return Result;
}
uint32_t Model::FaceCount() const
{
uint32_t Result = 0;
for (auto& Mesh : Meshes)
Result += Mesh.Faces.Count();
return Result;
}
void Model::GenerateLocalTransforms(bool Position, bool Rotation)
{
for (auto& Bone : Bones)
{
if (Bone.Parent() != -1)
{
if (Position)
{
auto ParentMatrix = Matrix::CreateFromQuaternion(~Bones[Bone.Parent()].GlobalRotation());
// Inverse parent matrix * parent position difference
Bone.SetLocalPosition(Matrix::TransformVector(Bone.GlobalPosition() - Bones[Bone.Parent()].GlobalPosition(), ParentMatrix));
}
// Inverse parent rotation * rotation
if (Rotation)
Bone.SetLocalRotation(~Bones[Bone.Parent()].GlobalRotation() * Bone.GlobalRotation());
}
else
{
// The global transform is the same as the local
if (Position)
Bone.SetLocalPosition(Bone.GlobalPosition());
if (Rotation)
Bone.SetLocalRotation(Bone.GlobalRotation());
}
}
}
void Model::GenerateGlobalTransforms(bool Position, bool Rotation)
{
for (auto& Bone : Bones)
{
if (Bone.Parent() != -1)
{
if (Position)
{
auto& ParentRotation = Bones[Bone.Parent()].GlobalRotation();
auto& ParentPosition = Bones[Bone.Parent()].GlobalPosition();
auto& LocalPosition = Bone.LocalPosition();
auto PositionQuaternion = Quaternion(LocalPosition.X, LocalPosition.Y, LocalPosition.Z, 0);
// Parent rotation * local position transform, then * inverse parent rotation
auto Result = (ParentRotation * PositionQuaternion) * ~ParentRotation;
// Add to the parent's global position
Bone.SetGlobalPosition({ ParentPosition.X + Result.X, ParentPosition.Y + Result.Y, ParentPosition.Z + Result.Z });
}
// Parent rotation * local rotation transform
if (Rotation)
Bone.SetGlobalRotation(Bones[Bone.Parent()].GlobalRotation() * Bone.LocalRotation());
}
else
{
// The local transform is the same as the global
if (Position)
Bone.SetGlobalPosition(Bone.LocalPosition());
if (Rotation)
Bone.SetGlobalRotation(Bone.LocalRotation());
}
}
}
void Model::CalculateVertexNormals()
{
for (auto& Mesh : Meshes)
{
for (auto& Vertex : Mesh.Vertices)
Vertex.SetNormal({ 0, 0, 0 });
for (auto& Face : Mesh.Faces)
{
auto CrossProduct = (Mesh.Vertices[Face[1]].Position() - Mesh.Vertices[Face[0]].Position()).Cross(Mesh.Vertices[Face[2]].Position() - Mesh.Vertices[Face[0]].Position());
Mesh.Vertices[Face[0]].SetNormal(Mesh.Vertices[Face[0]].Normal() + CrossProduct);
Mesh.Vertices[Face[1]].SetNormal(Mesh.Vertices[Face[1]].Normal() + CrossProduct);
Mesh.Vertices[Face[2]].SetNormal(Mesh.Vertices[Face[2]].Normal() + CrossProduct);
}
for (auto& Vertex : Mesh.Vertices)
Vertex.SetNormal(Vertex.Normal().GetNormalized());
}
}
void Model::Scale(float Factor)
{
for (auto& Bone : Bones)
{
Bone.SetLocalPosition(Bone.LocalPosition() * Factor);
Bone.SetGlobalPosition(Bone.GlobalPosition() * Factor);
}
for (auto& Mesh : Meshes)
{
for (auto& Vertex : Mesh.Vertices)
Vertex.SetPosition(Vertex.Position() * Factor);
}
}
}