Engine
Frameworkcreatedbymeusableforthecreationofsimplegames.CurrentlysupportsOpenGL(Verysimple)andVulkan.
VulkanMesh.cpp
Go to the documentation of this file.
2 #ifdef USING_VULKAN
4 #include "Engine/engine.hpp"
9 #include <ThirdParty/assimp/include/assimp/types.h>
10 
11 namespace Engine
12 {
13 
14  VulkanRenderer* VulkanMesh::renderer = nullptr;
15  VulkanLogicalDevice* VulkanMesh::device = nullptr;
16  VulkanDescriptorPool* VulkanMesh::descriptorPool = nullptr;
17  VkCommandPool VulkanMesh::commandPool = VK_NULL_HANDLE;
18  VmaAllocator VulkanMesh::allocator = VK_NULL_HANDLE;
19 
20  void VulkanMesh::InitMeshes(VulkanRenderer * renderer, VulkanLogicalDevice * device, VulkanDescriptorPool* descriptorPool, VkCommandPool commandPool)
21  {
22  VulkanMesh::renderer = renderer;
23  VulkanMesh::device = device;
24  VulkanMesh::descriptorPool = descriptorPool;
25  VulkanMesh::commandPool = commandPool;
26  VulkanMesh::allocator = renderer->GetVmaAllocator();
27  }
28 
29  VulkanMesh::VulkanMesh(aiMesh * mesh, eastl::shared_ptr<Skeleton> skeleton, eastl::vector<Vertex> vertices, eastl::vector<unsigned> indices) : Mesh(vertices, indices)
30  {
31  this->mesh = mesh;
32  this->skeleton = skeleton;
33 
34  SetUpMesh();
35  }
36 
37  VulkanMesh::~VulkanMesh()
38  {
39  vertexBuffer.reset();
40  indexBuffer.reset();
41  }
42 
43  void VulkanMesh::SetUpMesh()
44  {
45  //eastl::weak_ptr<VulkanRenderer> vulkanRenderer = Engine::GetRenderer<VulkanRenderer>();
46  //VkBuffer VBOBuffer, EBOBuffer, UBOBuffer;
47 
48  //vulkanRenderer->CreateBuffer<Vertex>(vertices, VBOBuffer, vertexBufferMemory, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT); //Creates a vertex buffer on GPU
49  //vulkanRenderer->CreateBuffer<uint32_t>(indices, EBOBuffer, indexBufferMemory, VK_BUFFER_USAGE_INDEX_BUFFER_BIT); // Creates Index buffer on GPU
50  //
51  //vulkanRenderer->CreateUniformBuffer(&UBOBuffer, &uniformBufferMemory); //Sends uniforms each frame to the GPU
52 
53  //vbo = uint64_t(VBOBuffer);
54  //ebo = uint64_t(EBOBuffer);
55  //ubo = uint64_t(UBOBuffer);
56 
57  animated = false;
58 
59  boneOffsets.resize(255, glm::mat4());
60 
61  if (mesh->HasBones() && skeleton != nullptr) {
62  //skeletal mesh, load bones
63  eastl::map<eastl::string, Skeleton::Bone_t*> boneMap = skeleton->GetBoneMap();
64 
65  for (size_t i = 0, size = mesh->mNumBones; i < size; ++i) {
66  if (boneMap.find(eastl::string(mesh->mBones[i]->mName.C_Str())) == boneMap.end()) {
67  eastl::string s = "Mesh references bone " +
68  eastl::string(mesh->mBones[i]->mName.C_Str()) +
69  " Which isn't found in skeleton " +
70  skeleton->GetName();
71  debug_warning("VulkanMesh", "Setup Mesh", s);
72  }
73  int index = boneMap[eastl::string(mesh->mBones[i]->mName.C_Str())]->boneDataIndex;
74  aiBone* bone = mesh->mBones[i];
75 
76  boneOffsets[index] = glm::mat4(bone->mOffsetMatrix.a1, bone->mOffsetMatrix.b1, bone->mOffsetMatrix.c1, bone->mOffsetMatrix.d1,
77  bone->mOffsetMatrix.a2, bone->mOffsetMatrix.b2, bone->mOffsetMatrix.c2, bone->mOffsetMatrix.d2,
78  bone->mOffsetMatrix.a3, bone->mOffsetMatrix.b3, bone->mOffsetMatrix.c3, bone->mOffsetMatrix.d3,
79  bone->mOffsetMatrix.a4, bone->mOffsetMatrix.b4, bone->mOffsetMatrix.c4, bone->mOffsetMatrix.d4);
80 
81  for (size_t j = 0; j < bone->mNumWeights; ++j) {
82  size_t id = 0;
83  float smallestWeight = vertices[bone->mWeights[j].mVertexId].boneWeights[id];
84 
85  for (size_t k = 0; k < 4; ++k) {
86  if (vertices[bone->mWeights[j].mVertexId].boneWeights[k] < smallestWeight) {
87  id = k;
88  smallestWeight = vertices[bone->mWeights[j].mVertexId].boneWeights[k];
89  }
90  }
91 
92  if (smallestWeight < bone->mWeights[j].mWeight) {
93  vertices[bone->mWeights[j].mVertexId].boneIds[id] = index;
94  vertices[bone->mWeights[j].mVertexId].boneWeights[id] = bone->mWeights[j].mWeight;
95  }
96 
97  }
98  }
99 
100  animated = true;
101  }
102 
103  vertexBuffer = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, allocator,
104  static_cast<uint32_t>(sizeof(Vertex)*vertices.size()), VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, true, commandPool));
105 
106  indexBuffer = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, allocator,
107  static_cast<uint32_t>(sizeof(uint32_t)*indices.size()), VK_BUFFER_USAGE_INDEX_BUFFER_BIT, true, commandPool));
108 
109  offsetBuffer = eastl::unique_ptr <VulkanBuffer>(new VulkanBuffer(device, allocator,
110  static_cast<uint32_t>(sizeof(glm::mat4) * 255), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, true, commandPool));
111 
112  eastl::map<aiVector3D, uint32_t> positionMap;
113  eastl::map<Edge, eastl::vector<Face>> neighbors;
114 
115  eastl::vector<Face> uniqueFaces;
116 
117  // Calculate adjacencies
118  for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
119  const aiFace& face = mesh->mFaces[i];
120 
121  Face unique;
122 
123  for (int j = 0; j < 3; ++j) {
124  uint32_t index = static_cast<uint32_t>(face.mIndices[j]);
125 
126  aiVector3D v = mesh->mVertices[index];
127 
128  if (positionMap.find(v) == positionMap.end()) {
129  positionMap[v] = index;
130  }
131  else {
132  index = positionMap[v];
133  }
134 
135  unique.indices[j] = index;
136 
137  }
138 
139  uniqueFaces.push_back(unique);
140 
141  Edge edge1(unique.indices[0], unique.indices[1]);
142  Edge edge2(unique.indices[1], unique.indices[2]);
143  Edge edge3(unique.indices[2], unique.indices[0]);
144 
145  neighbors[edge1].push_back(unique);
146  neighbors[edge2].push_back(unique);
147  neighbors[edge3].push_back(unique);
148  }
149 
150  eastl::vector<uint32_t> intIndices(indices.size());
151 
152  for (size_t i = 0, size = indices.size(); i < size; ++i) {
153  intIndices[i] = static_cast<uint32_t>(indices[i]);
154  }
155 
156  eastl::vector<uint32_t> shadowIndices(uniqueFaces.size() * 6);
157 
158  shadowIndicesCount = static_cast<uint32_t>(uniqueFaces.size() * 6);
159 
160  for (size_t i = 0, size = uniqueFaces.size(); i < size; ++i) {
161  Face face = uniqueFaces[i];
162 
163  Edge edge1(face.indices[0], face.indices[1]);
164  Edge edge2(face.indices[1], face.indices[2]);
165  Edge edge3(face.indices[2], face.indices[0]);
166 
167  Face neighbor1;
168  Face neighbor2;
169  Face neighbor3;
170 
171  eastl::vector<Face> edge1Neighbors = neighbors[edge1];
172  eastl::vector<Face> edge2Neighbors = neighbors[edge2];
173  eastl::vector<Face> edge3Neighbors = neighbors[edge3];
174 
175  if (edge1Neighbors.size() < 2)
176  neighbor1 = face;
177  else
178  neighbor1 = edge1Neighbors[0] == face ? edge1Neighbors[1] : edge1Neighbors[0];
179  if (edge2Neighbors.size() < 2)
180  neighbor2 = face;
181  else
182  neighbor2 = edge2Neighbors[0] == face ? edge2Neighbors[1] : edge2Neighbors[0];
183  if (edge3Neighbors.size() < 2)
184  neighbor3 = face;
185  else
186  neighbor3 = edge3Neighbors[0] == face ? edge3Neighbors[1] : edge3Neighbors[0];
187 
188  shadowIndices[i * 6 + 0] = static_cast<uint32_t>(face.indices[0]);
189 
190  if (neighbor1 == face)
191  shadowIndices[i * 6 + 1] = face.indices[2];
192  else
193  shadowIndices[i * 6 + 1] = neighbor1.FindOpposingIndex(edge1);
194 
195  shadowIndices[i * 6 + 2] = static_cast<uint32_t>(face.indices[1]);
196 
197  if (neighbor2 == face)
198  shadowIndices[i * 6 + 3] = face.indices[0];
199  else
200  shadowIndices[i * 6 + 3] = neighbor2.FindOpposingIndex(edge2);
201 
202  shadowIndices[i * 6 + 4] = static_cast<uint32_t>(face.indices[2]);
203 
204  if (neighbor3 == face)
205  shadowIndices[i * 6 + 5] = face.indices[1];
206  else
207  shadowIndices[i * 6 + 5] = neighbor3.FindOpposingIndex(edge3);
208  }
209 
210  shadowIndexBuffer = eastl::unique_ptr<VulkanBuffer>(new VulkanBuffer(device, allocator,
211  static_cast<uint32_t>(sizeof(uint32_t)*shadowIndicesCount),
212  VK_BUFFER_USAGE_INDEX_BUFFER_BIT, true, commandPool));
213 
214  vertexBuffer->UpdateBuffer(vertices.data(), 0, static_cast<uint32_t>(sizeof(Vertex)*vertices.size()));
215  indexBuffer->UpdateBuffer(intIndices.data(), 0, static_cast<uint32_t>(sizeof(uint32_t)*intIndices.size()));
216  offsetBuffer->UpdateBuffer(boneOffsets.data(), 0, static_cast<uint32_t>(sizeof(glm::mat4) * 255));
217 
218  shadowIndexBuffer->UpdateBuffer(shadowIndices.data(), 0,
219  static_cast<uint32_t>(sizeof(uint32_t)*shadowIndicesCount));
220 
221  }
222 
223  VkBuffer VulkanMesh::GetVertexBuffer() const
224  {
225  return vertexBuffer->GetBuffer();
226  }
227 
228  VkBuffer VulkanMesh::GetIndexBuffer() const
229  {
230  return indexBuffer->GetBuffer();
231  }
232 
233  VkBuffer VulkanMesh::GetShadowIndexBuffer() const
234  {
235  return shadowIndexBuffer->GetBuffer();
236  }
237 
238  uint32_t VulkanMesh::GetShadowIndexCount() const
239  {
240  return shadowIndicesCount;
241  }
242 
243  uint32_t VulkanMesh::GetIndexCount()
244  {
245  return static_cast<uint32_t>(indices.size());
246  }
247 
248  bool VulkanMesh::IsAnimated() const
249  {
250  return animated;
251  }
252 
253  VkDescriptorSet VulkanMesh::CreateBoneOffsetDescriptorSet(size_t threadID, size_t pipelineID, size_t set, VkDescriptorSetLayout layout)
254  {
255  if (offsetDescriptorSets.size() <= pipelineID) {
256  offsetDescriptorSets.resize(pipelineID + 1);
257  }
258  if (offsetDescriptorSets[pipelineID].size() <= set) {
259  offsetDescriptorSets[pipelineID].resize(set + 1);
260  }
261  if (offsetDescriptorSets[pipelineID][set].size() <= threadID) {
262  offsetDescriptorSets[pipelineID][set].resize(threadID + 1, VK_NULL_HANDLE);
263  }
264 
265  VkDescriptorSetLayout layouts[] = { layout };
266  renderer->GetDescriptorPool(threadID)->AllocateDescriptorSet(1, layouts, &offsetDescriptorSets[pipelineID][set][threadID]);
267 
268  renderer->GetDescriptorPool(threadID)->DescriptorSetBindToBuffer(offsetDescriptorSets[pipelineID][set][threadID], offsetBuffer->GetBuffer(),
269  0, static_cast<VkDeviceSize>(sizeof(glm::mat4) * 255), 0, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1);
270 
271  return offsetDescriptorSets[pipelineID][set][threadID];
272  }
273 
274  VkDescriptorSet VulkanMesh::GetBoneOffsetDescriptorSet(size_t threadID, size_t pipelineID, size_t set)
275  {
276  if (pipelineID >= offsetDescriptorSets.size())
277  return VK_NULL_HANDLE;
278  if (set >= offsetDescriptorSets[pipelineID].size())
279  return VK_NULL_HANDLE;
280  if (threadID >= offsetDescriptorSets[pipelineID][set].size())
281  return VK_NULL_HANDLE;
282  return offsetDescriptorSets[pipelineID][set][threadID];
283  }
284 } //namespace Engine
285 #endif
eastl::vector< unsigned > indices
The indices of this mesh.
Definition: Mesh.hpp:24
eastl::vector< Vertex > vertices
The vertices of this mesh.
Definition: Mesh.hpp:20
#define debug_warning(debug_class, function, value)
This functions logs a debug warning to the log and console.
Definition: Logging.hpp:45
This object is used to store general data for a vertex.
Definition: Vertex.hpp:6