1#include <assimp/Importer.hpp> 
    2#include <assimp/postprocess.h> 
    4#define GLM_ENABLE_EXPERIMENTAL 
    5#include <glm/gtx/hash.hpp> 
   12struct std::hash<
ven::Model::Vertex> {
 
   15        ven::hashCombine(seed, vertex.position, vertex.color, vertex.normal, vertex.uv);
 
 
 
   28    m_vertexCount = 
static_cast<uint32_t
>(vertices.size());
 
   29    assert(m_vertexCount >= 3 && 
"Vertex count must be at least 3");
 
   30    constexpr unsigned long vertexSize = 
sizeof(vertices[0]);
 
   31    const VkDeviceSize bufferSize = vertexSize * m_vertexCount;
 
   33    Buffer stagingBuffer{m_device, vertexSize, m_vertexCount, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT};
 
   36    stagingBuffer.writeToBuffer(vertices.data());
 
   38    m_vertexBuffer = std::make_unique<Buffer>(m_device, vertexSize, m_vertexCount, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 
   40    m_device.copyBuffer(stagingBuffer.getBuffer(), m_vertexBuffer->getBuffer(), bufferSize);
 
 
   45    m_indexCount = 
static_cast<uint32_t
>(indices.size());
 
   46    m_hasIndexBuffer = m_indexCount > 0;
 
   48    if (!m_hasIndexBuffer) {
 
   52    constexpr uint32_t indexSize = 
sizeof(indices[0]);
 
   54    Buffer stagingBuffer{m_device, indexSize, m_indexCount, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT};
 
   57    stagingBuffer.writeToBuffer(indices.data());
 
   59    m_indexBuffer = std::make_unique<Buffer>(m_device, indexSize, m_indexCount, VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
 
   61    m_device.copyBuffer(stagingBuffer.getBuffer(), m_indexBuffer->getBuffer(), 
sizeof(indices[0]) * m_indexCount);
 
 
   66    if (m_hasIndexBuffer) {
 
   67        vkCmdDrawIndexed(commandBuffer, m_indexCount, 1, 0, 0, 0);
 
   69        vkCmdDraw(commandBuffer, m_vertexCount, 1, 0, 0);
 
 
   75    const std::array buffers{m_vertexBuffer->getBuffer()};
 
   76    constexpr std::array<VkDeviceSize, 1> offsets{0};
 
   77    vkCmdBindVertexBuffers(commandBuffer, 0, 1, buffers.data(), offsets.data());
 
   79    if (m_hasIndexBuffer) {
 
   80        vkCmdBindIndexBuffer(commandBuffer, m_indexBuffer->getBuffer(), 0, VK_INDEX_TYPE_UINT32);
 
 
   86    std::vector<VkVertexInputBindingDescription> bindingDescriptions(1);
 
   87    bindingDescriptions[0].binding = 0;
 
   88    bindingDescriptions[0].stride = 
sizeof(
Vertex);
 
   89    bindingDescriptions[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
 
   90    return bindingDescriptions;
 
 
   95    std::vector<VkVertexInputAttributeDescription> attributeDescriptions{};
 
   97    attributeDescriptions.push_back({0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(
Vertex, position)});
 
   98    attributeDescriptions.push_back({1, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(
Vertex, color)});
 
   99    attributeDescriptions.push_back({2, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(
Vertex, normal)});
 
  100    attributeDescriptions.push_back({3, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(
Vertex, uv)});
 
  102    return attributeDescriptions;
 
 
  107    Assimp::Importer importer;
 
  109    const aiScene* scene = importer.ReadFile(filename, aiProcess_Triangulate | aiProcess_FlipUVs | aiProcess_CalcTangentSpace | aiProcess_GenNormals);
 
  111    if ((scene == 
nullptr) || ((scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE) != 0U) || (scene->mRootNode == 
nullptr)) {
 
  112        throw std::runtime_error(
"Failed to load model with Assimp: " + std::string(importer.GetErrorString()));
 
  118    processNode(scene->mRootNode, scene);
 
 
  122    for (
unsigned int i = 0; i < node->mNumMeshes; i++) {
 
  123        const aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
 
  124        processMesh(mesh, scene);
 
  127    for (
unsigned int i = 0; i < node->mNumChildren; i++) {
 
  128        processNode(node->mChildren[i], scene);
 
 
  133    std::unordered_map<Vertex, uint32_t> uniqueVertices;
 
  135    for (
unsigned int i = 0; i < mesh->mNumVertices; i++) {
 
  139            mesh->mVertices[i].x,
 
  140            mesh->mVertices[i].y,
 
  144        if (mesh->HasNormals()) {
 
  145            vertex.normal = glm::vec3(
 
  152        if (mesh->mTextureCoords[0] != 
nullptr) {
 
  153            vertex.uv = glm::vec2(
 
  154                mesh->mTextureCoords[0][i].x,
 
  155                mesh->mTextureCoords[0][i].y
 
  158            vertex.uv = glm::vec2(0.0F, 0.0F);
 
  161        if (!uniqueVertices.contains(vertex)) {
 
  162            uniqueVertices[vertex] = 
static_cast<uint32_t
>(vertices.size());
 
  163            vertices.push_back(vertex);
 
  166        indices.push_back(uniqueVertices[vertex]);
 
 
This file contains the Model class.
 
VkResult map(VkDeviceSize size=VK_WHOLE_SIZE, VkDeviceSize offset=0)
Map a memory range of this buffer.
 
void draw(VkCommandBuffer commandBuffer) const
 
Model(Device &device, const Builder &builder)
 
void bind(VkCommandBuffer commandBuffer) const
 
void createVertexBuffer(const std::vector< Vertex > &vertices)
 
void createIndexBuffer(const std::vector< uint32_t > &indices)
 
void hashCombine(std::size_t &seed, const T &v, const Rest &... rest)
 
size_t operator()(ven::Model::Vertex const &vertex) const noexcept
 
void loadModel(const std::string &filename)
 
std::vector< Vertex > vertices
 
void processMesh(const aiMesh *mesh, const aiScene *scene)
 
std::vector< uint32_t > indices
 
void processNode(const aiNode *node, const aiScene *scene)
 
static std::vector< VkVertexInputAttributeDescription > getAttributeDescriptions()
 
static std::vector< VkVertexInputBindingDescription > getBindingDescriptions()