LkEngine 0.1.2
 
Loading...
Searching...
No Matches
Mesh.h
1#pragma once
2
4#include "LkEngine/Core/LObject/ObjectPtr.h"
5#include "LkEngine/Core/Math/AABB.h"
6
7#include "LkEngine/Asset/Asset.h"
8#include "LkEngine/Asset/MaterialAsset.h"
9
10#include "LkEngine/Serialization/FileStream.h"
11
12#include "VertexBuffer.h"
13#include "Texture.h"
14#include "Material.h"
15
16#include <filesystem>
17
18#include <assimp/Importer.hpp>
19#include <assimp/scene.h>
20#include <assimp/postprocess.h>
21
22namespace LkEngine {
23
27 struct FVertex
28 {
29 glm::vec3 Position{};
30 glm::vec3 Normal{};
31 glm::vec3 Tangent{};
32 glm::vec3 Binormal{};
33 glm::vec2 Texcoord{};
34 };
35
39 struct FBoneInfo
40 {
41 glm::mat4 SubMeshInverseTransform;
42 glm::mat4 InverseBindPose;
43 uint32_t SubMeshIndex;
44 uint32_t BoneIndex;
45
46 FBoneInfo() = default;
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)
55 {
56 }
57
58 FORCEINLINE static void Serialize(StreamWriter* Serializer, const FBoneInfo& BoneInfo)
59 {
60 Serializer->WriteRaw(BoneInfo);
61 }
62
63 FORCEINLINE static void Deserialize(StreamReader* Deserializer, FBoneInfo& BoneInfo)
64 {
65 Deserializer->ReadRaw(BoneInfo);
66 }
67 };
68
73 {
74 uint32_t BoneInfoIndices[4] = { 0, 0, 0, 0 };
75 float Weights[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
76
77 FORCEINLINE void AddBoneData(const uint32_t BoneInfoIndex, float Weight)
78 {
79 if ((Weight < 0.0f) || (Weight > 1.0f))
80 {
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);
84 }
85
86 if (Weight > 0.0f)
87 {
88 for (size_t i = 0; i < 4; i++)
89 {
90 if (Weights[i] == 0.0f)
91 {
92 BoneInfoIndices[i] = BoneInfoIndex;
93 Weights[i] = Weight;
94
95 return;
96 }
97 }
98
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);
102 }
103 }
104
105 FORCEINLINE void NormalizeWeights()
106 {
107 float WeightSum = 0.0f;
108
109 for (size_t i = 0; i < 4; i++)
110 {
111 WeightSum += Weights[i];
112 }
113
114 if (WeightSum > 0.0f)
115 {
116 for (size_t i = 0; i < 4; i++)
117 {
118 Weights[i] /= WeightSum;
119 }
120 }
121 }
122
123 static void Serialize(StreamWriter* Serializer, const FBoneInfluence& BoneInfluence)
124 {
125 Serializer->WriteRaw(BoneInfluence);
126 }
127
128 static void Deserialize(StreamReader* Deserializer, FBoneInfluence& BoneInfluence)
129 {
130 Deserializer->ReadRaw(BoneInfluence);
131 }
132 };
133
134 static const int NumAttributes = 5;
135
139 struct FIndex
140 {
141 uint32_t V1{};
142 uint32_t V2{};
143 uint32_t V3{};
144 };
145 static_assert(sizeof(FIndex) == (3 * sizeof(uint32_t)));
146
151 {
152 FVertex V0;
153 FVertex V1;
154 FVertex V2;
155
156 explicit FTriangle(const FVertex& InV0,
157 const FVertex& InV1,
158 const FVertex& InV2)
159 : V0(InV0)
160 , V1(InV1)
161 , V2(InV2)
162 {
163 }
164 FTriangle() = delete;
165 };
166
168 {
169 public:
170 LSubmesh() = default;
171 ~LSubmesh() = default;
172
173 uint32_t BaseVertex{};
174 uint32_t BaseIndex{};
175 uint32_t MaterialIndex{};
176 uint32_t IndexCount{};
177 uint32_t VertexCount{};
178
180 glm::mat4 Transform{ 1.0f };
181
183 glm::mat4 LocalTransform{ 1.0f };
184
185 FAABB BoundingBox{};
186
187 std::string NodeName{};
188 std::string MeshName{};
189 bool bIsRigged = false;
190
191 static void Serialize(StreamWriter* Serializer, const LSubmesh& Submesh)
192 {
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);
204 }
205
206 static void Deserialize(StreamReader* Deserializer, LSubmesh& Submesh)
207 {
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);
219 }
220
221 std::string ToString() const
222 {
223 return LK_FMT_LIB::format("[Submesh: {}] VertexCount={} IndexCount={} MaterialIndex={}", MeshName, VertexCount, IndexCount, MaterialIndex);
224 }
225 };
226
228 {
229 uint32_t Parent = 0xFFFFFFFF;
230 std::vector<uint32_t> Children{};
231 std::vector<uint32_t> Submeshes{};
232
233 std::string Name{};
234 glm::mat4 LocalTransform{};
235
236 FORCEINLINE bool IsRoot() const
237 {
238 return (Parent == 0xFFFFFFFF);
239 }
240
241 static void Serialize(StreamWriter* Serializer, const FMeshNode& MeshNode)
242 {
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);
249 }
250
251 static void Deserialize(StreamReader* Deserializer, FMeshNode& MeshNode)
252 {
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);
259 }
260 };
261
265 class LMeshSource : public LAsset
266 {
267 public:
268 LMeshSource();
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);
271 virtual ~LMeshSource() = default;
272
273 FORCEINLINE std::vector<LSubmesh>& GetSubmeshes() { return Submeshes; }
274 FORCEINLINE const std::vector<LSubmesh>& GetSubmeshes() const { return Submeshes; }
275
276 FORCEINLINE const std::vector<FVertex>& GetVertices() const { return Vertices; }
277 FORCEINLINE const std::vector<FIndex>& GetIndices() const { return Indices; }
278
279 FORCEINLINE bool IsSubmeshRigged(const uint32_t SubmeshIndex) const
280 {
281 LK_CORE_ASSERT(!Submeshes.empty() && (SubmeshIndex < Submeshes.size()));
282 return Submeshes[SubmeshIndex].bIsRigged;
283 }
284
285 FORCEINLINE const std::vector<FBoneInfluence>& GetBoneInfluences() const
286 {
287 return BoneInfluences;
288 }
289
290 FORCEINLINE std::vector<TObjectPtr<LMaterial>>& GetMaterials()
291 {
292 return Materials;
293 }
294
295 FORCEINLINE const std::vector<TObjectPtr<LMaterial>>& GetMaterials() const
296 {
297 return Materials;
298 }
299
300 FORCEINLINE const std::filesystem::path& GetFilePath() const
301 {
302 return FilePath;
303 }
304
305 FORCEINLINE const std::vector<FTriangle> GetTriangleCache(const uint32_t Index) const
306 {
307 LK_VERIFY(TriangleCache.contains(Index));
308 return TriangleCache.at(Index);
309 }
310
311 FORCEINLINE TObjectPtr<LVertexBuffer> GetVertexBuffer()
312 {
313 LK_CORE_ASSERT(VertexBuffer);
314 return VertexBuffer;
315 }
316
317 FORCEINLINE TObjectPtr<LIndexBuffer> GetIndexBuffer()
318 {
319 LK_CORE_ASSERT(IndexBuffer);
320 return IndexBuffer;
321 }
322
323 FORCEINLINE TObjectPtr<LVertexBuffer> GetBoneInfluenceBuffer()
324 {
325 return BoneInfluenceBuffer;
326 }
327
328 static EAssetType GetStaticType() { return EAssetType::MeshSource; }
329 //const FAABB& GetBoundingBox() const { return m_BoundingBox; }
330
331 FORCEINLINE const std::vector<FMeshNode>& GetNodes() const
332 {
333 return MeshNodes;
334 }
335
336 FORCEINLINE const FMeshNode& GetRootNode() const
337 {
338 LK_CORE_ASSERT(!MeshNodes.empty(), "No root node exists");
339 return MeshNodes[0];
340 }
341
345 void DumpVertexBuffer();
346
347 private:
348 std::vector<LSubmesh> Submeshes{};
349
350 TObjectPtr<LVertexBuffer> VertexBuffer{};
351 TObjectPtr<LVertexBuffer> BoneInfluenceBuffer{};
352 TObjectPtr<LIndexBuffer> IndexBuffer{};
353
354 std::vector<FVertex> Vertices{};
355 std::vector<FIndex> Indices{};
356
357 std::vector<FBoneInfluence> BoneInfluences{};
358 std::vector<FBoneInfo> BoneInfo{};
359
360 std::vector<TObjectPtr<LMaterial>> Materials{};
361 std::unordered_map<uint32_t, std::vector<FTriangle>> TriangleCache;
362 std::vector<FMeshNode> MeshNodes{};
363 FAABB BoundingBox{};
364
365 std::filesystem::path FilePath{};
366
367 friend class LScene;
368 friend class LSceneRenderer;
369 friend class LRenderer;
370 friend class LOpenGLRenderer;
371 friend class LMesh;
372 friend class LAssimpMeshImporter;
373 friend class LAssetManager;
374 friend class LEditorAssetManager;
375 friend class LRuntimeAssetManager;
376
378 };
379
385 class LMesh : public LAsset
386 {
387 public:
388 explicit LMesh(TObjectPtr<LMeshSource> MeshSource);
389 LMesh(TObjectPtr<LMeshSource> InMeshSource, const std::vector<uint32_t>& InSubmeshes);
390 LMesh(const TObjectPtr<LMesh>& Other);
391 virtual ~LMesh() = default;
392
393 std::vector<uint32_t>& GetSubmeshes() { return Submeshes; }
394 const std::vector<uint32_t>& GetSubmeshes() const { return Submeshes; }
395
396 void SetSubmeshes(const std::vector<uint32_t>& InSubmeshes);
397
398 TObjectPtr<LMeshSource> GetMeshSource() { return MeshSource; }
399 TObjectPtr<LMeshSource> GetMeshSource() const { return MeshSource; }
400
401 void SetMeshAsset(TObjectPtr<LMeshSource> InMeshSource)
402 {
403 MeshSource = InMeshSource;
404 }
405
406 TObjectPtr<LMaterialTable> GetMaterialTable() const { return MaterialTable; }
407
408 static EAssetType GetStaticType() { return EAssetType::Mesh; }
409
410 /* TODO: Remove GetVertexBuffer and GetIndexBuffer. */
411 TObjectPtr<LVertexBuffer> GetVertexBuffer() { return MeshSource->GetVertexBuffer(); }
412 TObjectPtr<LIndexBuffer> GetIndexBuffer() { return MeshSource->GetIndexBuffer(); }
413
414 TObjectPtr<LMaterial> GetMaterial(const uint32_t Index = 0);
415
416 FAssetHandle GetMaterialHandle(const uint32_t Index)
417 {
418 LK_CORE_ASSERT(MaterialTable && MaterialTable->HasMaterial(Index));
419 return MaterialTable->GetMaterial(Index);
420 }
421
422 const std::string& GetName() const { return Name; }
423 void SetName(const std::string& InName) { Name = InName; }
424
425 private:
426 TObjectPtr<LMeshSource> MeshSource{};
427 std::vector<uint32_t> Submeshes{};
428 TObjectPtr<LMaterialTable> MaterialTable{};
429
430 std::string Name{};
431
432 friend class LAssetManager;
433 friend class LScene;
434 friend class LRenderer;
435 friend class LSceneRenderer;
436 friend class LRuntimeAssetManager;
437 friend class LOpenGLRenderer;
438
440 };
441
445 class LStaticMesh : public LAsset
446 {
447 public:
448 explicit LStaticMesh(TObjectPtr<LMeshSource> InMeshSource);
449 LStaticMesh(TObjectPtr<LMeshSource> InMeshSource, const std::vector<uint32_t>& InSubmeshes);
451 virtual ~LStaticMesh() = default;
452
453 std::vector<uint32_t>& GetSubmeshes() { return Submeshes; }
454 const std::vector<uint32_t>& GetSubmeshes() const { return Submeshes; }
455
456 void SetSubmeshes(const std::vector<uint32_t>& InSubmeshes);
457
458 TObjectPtr<LMeshSource> GetMeshSource() { return MeshSource; }
459 TObjectPtr<LMeshSource> GetMeshSource() const { return MeshSource; }
460
461 void SetMeshAsset(TObjectPtr<LMeshSource> InMeshAsset)
462 {
463 MeshSource = InMeshAsset;
464 }
465
466 TObjectPtr<LMaterialTable> GetMaterialTable() const
467 {
468 LK_CORE_ASSERT(MaterialTable);
469 return MaterialTable;
470 }
471
472 static EAssetType GetStaticType() { return EAssetType::StaticMesh; }
473
474 void SetName(const std::string& InName) { Name = InName; }
475
476 private:
477 TObjectPtr<LMeshSource> MeshSource{};
478 std::vector<uint32_t> Submeshes{};
479
480 TObjectPtr<LMaterialTable> MaterialTable{};
481
482 std::string Name{};
483
484 friend class LAssetManager;
485 friend class LScene;
486 friend class LRenderer;
487 friend class LSceneRenderer;
488 friend class LRuntimeAssetManager;
489 friend class LOpenGLRenderer;
490 friend class LSceneHierarchyPanel;
491 friend class LMeshViewerPanel;
492
494 };
495
496
497}
LObject implementation.
Definition AssetManager.h:16
Definition Asset.h:21
Definition AssimpMeshImporter.h:13
Definition EditorAssetManager.h:31
Definition Mesh.h:266
void DumpVertexBuffer()
Definition Mesh.cpp:75
Definition Mesh.h:386
Definition OpenGLRenderer.h:21
Definition Renderer.h:18
Definition RuntimeAssetManager.h:9
Definition SceneRenderer.h:37
Definition Scene.h:47
Definition Mesh.h:446
void SetSubmeshes(const std::vector< uint32_t > &InSubmeshes)
Definition Mesh.cpp:248
Definition Mesh.h:168
glm::mat4 LocalTransform
Definition Mesh.h:183
glm::mat4 Transform
Definition Mesh.h:180
Definition StreamReader.h:12
Definition StreamWriter.h:9
Definition ObjectPtr.h:102
#define LASSET(Class)
Definition CoreMacros.h:316
Definition Asset.h:11
EAssetType
Definition AssetTypes.h:24
Definition AABB.h:9
Definition Mesh.h:73
Definition Mesh.h:40
Definition Mesh.h:140
Definition Mesh.h:228
Definition Mesh.h:151
Definition Mesh.h:28
Definition UUID.h:13