41 glm::mat4 SubMeshInverseTransform;
42 glm::mat4 InverseBindPose;
43 uint32_t SubMeshIndex;
47 FBoneInfo(
const glm::mat4& InSubMeshInverseTransform,
48 const glm::mat4& InInverseBindPose,
49 const uint32_t InSubMeshIndex,
50 const uint32_t InBoneIndex)
51 : SubMeshInverseTransform(InSubMeshInverseTransform)
52 , InverseBindPose(InInverseBindPose)
53 , SubMeshIndex(InSubMeshIndex)
54 , BoneIndex(InBoneIndex)
60 Serializer->WriteRaw(BoneInfo);
65 Deserializer->ReadRaw(BoneInfo);
74 uint32_t BoneInfoIndices[4] = { 0, 0, 0, 0 };
75 float Weights[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
77 FORCEINLINE
void AddBoneData(
const uint32_t BoneInfoIndex,
float Weight)
79 if ((Weight < 0.0f) || (Weight > 1.0f))
81 LK_CORE_WARN_TAG(
"BoneInfluence",
"Vertex bone weight is out of range, clamping it to [0, 1] (BoneID={}, Weight={})",
82 BoneInfoIndex, Weight);
83 Weight = std::clamp(Weight, 0.0f, 1.0f);
88 for (
size_t i = 0; i < 4; i++)
90 if (Weights[i] == 0.0f)
92 BoneInfoIndices[i] = BoneInfoIndex;
99 LK_CORE_WARN_TAG(
"BoneInfluence",
"Vertex has more than four bones affecting it, "
100 "extra bone influences will be discarded (BoneID={}, Weight={})",
101 BoneInfoIndex, Weight);
105 FORCEINLINE
void NormalizeWeights()
107 float WeightSum = 0.0f;
109 for (
size_t i = 0; i < 4; i++)
111 WeightSum += Weights[i];
114 if (WeightSum > 0.0f)
116 for (
size_t i = 0; i < 4; i++)
118 Weights[i] /= WeightSum;
125 Serializer->WriteRaw(BoneInfluence);
130 Deserializer->ReadRaw(BoneInfluence);
173 uint32_t BaseVertex{};
174 uint32_t BaseIndex{};
175 uint32_t MaterialIndex{};
176 uint32_t IndexCount{};
177 uint32_t VertexCount{};
187 std::string NodeName{};
188 std::string MeshName{};
189 bool bIsRigged =
false;
191 static void Serialize(StreamWriter* Serializer,
const LSubmesh& Submesh)
193 Serializer->WriteRaw(Submesh.BaseVertex);
194 Serializer->WriteRaw(Submesh.BaseIndex);
195 Serializer->WriteRaw(Submesh.MaterialIndex);
196 Serializer->WriteRaw(Submesh.IndexCount);
197 Serializer->WriteRaw(Submesh.VertexCount);
198 Serializer->WriteRaw(Submesh.Transform);
199 Serializer->WriteRaw(Submesh.LocalTransform);
200 Serializer->WriteRaw(Submesh.BoundingBox);
201 Serializer->WriteString(Submesh.NodeName);
202 Serializer->WriteString(Submesh.MeshName);
203 Serializer->WriteRaw(Submesh.bIsRigged);
206 static void Deserialize(StreamReader* Deserializer, LSubmesh& Submesh)
208 Deserializer->ReadRaw(Submesh.BaseVertex);
209 Deserializer->ReadRaw(Submesh.BaseIndex);
210 Deserializer->ReadRaw(Submesh.MaterialIndex);
211 Deserializer->ReadRaw(Submesh.IndexCount);
212 Deserializer->ReadRaw(Submesh.VertexCount);
213 Deserializer->ReadRaw(Submesh.Transform);
214 Deserializer->ReadRaw(Submesh.LocalTransform);
215 Deserializer->ReadRaw(Submesh.BoundingBox);
216 Deserializer->ReadString(Submesh.NodeName);
217 Deserializer->ReadString(Submesh.MeshName);
218 Deserializer->ReadRaw(Submesh.bIsRigged);
221 std::string ToString()
const
223 return LK_FMT_LIB::format(
"[Submesh: {}] VertexCount={} IndexCount={} MaterialIndex={}", MeshName, VertexCount, IndexCount, MaterialIndex);
229 uint32_t Parent = 0xFFFFFFFF;
230 std::vector<uint32_t> Children{};
231 std::vector<uint32_t> Submeshes{};
234 glm::mat4 LocalTransform{};
236 FORCEINLINE
bool IsRoot()
const
238 return (Parent == 0xFFFFFFFF);
243 LK_VERIFY(Serializer);
244 Serializer->WriteRaw(MeshNode.Parent);
245 Serializer->WriteArray(MeshNode.Children);
246 Serializer->WriteArray(MeshNode.Submeshes);
247 Serializer->WriteString(MeshNode.Name);
248 Serializer->WriteRaw(MeshNode.LocalTransform);
253 LK_VERIFY(Deserializer);
254 Deserializer->ReadRaw(MeshNode.Parent);
255 Deserializer->ReadArray(MeshNode.Children);
256 Deserializer->ReadArray(MeshNode.Submeshes);
257 Deserializer->ReadString(MeshNode.Name);
258 Deserializer->ReadRaw(MeshNode.LocalTransform);
269 LMeshSource(
const std::vector<FVertex>& InVertices,
const std::vector<FIndex>& InIndices,
const glm::mat4& InTransform);
270 LMeshSource(
const std::vector<FVertex>& InVertices,
const std::vector<FIndex>& InIndices,
const std::vector<LSubmesh>& InSubmeshes);
273 FORCEINLINE std::vector<LSubmesh>& GetSubmeshes() {
return Submeshes; }
274 FORCEINLINE
const std::vector<LSubmesh>& GetSubmeshes()
const {
return Submeshes; }
276 FORCEINLINE
const std::vector<FVertex>& GetVertices()
const {
return Vertices; }
277 FORCEINLINE
const std::vector<FIndex>& GetIndices()
const {
return Indices; }
279 FORCEINLINE
bool IsSubmeshRigged(
const uint32_t SubmeshIndex)
const
281 LK_CORE_ASSERT(!Submeshes.empty() && (SubmeshIndex < Submeshes.size()));
282 return Submeshes[SubmeshIndex].bIsRigged;
285 FORCEINLINE
const std::vector<FBoneInfluence>& GetBoneInfluences()
const
287 return BoneInfluences;
290 FORCEINLINE std::vector<TObjectPtr<LMaterial>>& GetMaterials()
295 FORCEINLINE
const std::vector<TObjectPtr<LMaterial>>& GetMaterials()
const
300 FORCEINLINE
const std::filesystem::path& GetFilePath()
const
305 FORCEINLINE
const std::vector<FTriangle> GetTriangleCache(
const uint32_t Index)
const
307 LK_VERIFY(TriangleCache.contains(Index));
308 return TriangleCache.at(Index);
313 LK_CORE_ASSERT(VertexBuffer);
319 LK_CORE_ASSERT(IndexBuffer);
325 return BoneInfluenceBuffer;
328 static EAssetType GetStaticType() {
return EAssetType::MeshSource; }
331 FORCEINLINE
const std::vector<FMeshNode>& GetNodes()
const
336 FORCEINLINE
const FMeshNode& GetRootNode()
const
338 LK_CORE_ASSERT(!MeshNodes.empty(),
"No root node exists");
348 std::vector<LSubmesh> Submeshes{};
354 std::vector<FVertex> Vertices{};
355 std::vector<FIndex> Indices{};
357 std::vector<FBoneInfluence> BoneInfluences{};
358 std::vector<FBoneInfo> BoneInfo{};
360 std::vector<TObjectPtr<LMaterial>> Materials{};
361 std::unordered_map<uint32_t, std::vector<FTriangle>> TriangleCache;
362 std::vector<FMeshNode> MeshNodes{};
365 std::filesystem::path FilePath{};
391 virtual ~LMesh() =
default;
393 std::vector<uint32_t>& GetSubmeshes() {
return Submeshes; }
394 const std::vector<uint32_t>& GetSubmeshes()
const {
return Submeshes; }
396 void SetSubmeshes(
const std::vector<uint32_t>& InSubmeshes);
403 MeshSource = InMeshSource;
408 static EAssetType GetStaticType() {
return EAssetType::Mesh; }
418 LK_CORE_ASSERT(MaterialTable && MaterialTable->HasMaterial(Index));
419 return MaterialTable->GetMaterial(Index);
422 const std::string& GetName()
const {
return Name; }
423 void SetName(
const std::string& InName) { Name = InName; }
427 std::vector<uint32_t> Submeshes{};
453 std::vector<uint32_t>& GetSubmeshes() {
return Submeshes; }
454 const std::vector<uint32_t>& GetSubmeshes()
const {
return Submeshes; }
456 void SetSubmeshes(
const std::vector<uint32_t>& InSubmeshes);
463 MeshSource = InMeshAsset;
468 LK_CORE_ASSERT(MaterialTable);
469 return MaterialTable;
472 static EAssetType GetStaticType() {
return EAssetType::StaticMesh; }
474 void SetName(
const std::string& InName) { Name = InName; }
478 std::vector<uint32_t> Submeshes{};
490 friend class LSceneHierarchyPanel;
491 friend class LMeshViewerPanel;