Newer
Older
ForwardPlusRenderer / src / ModelLoading.cpp
#pragma once
#include <stdafx.h>
#include <ModelLoading.h>
#include <glm/gtc/type_ptr.hpp>
#include <variant>
#include "Vertex.h"
#include "Mesh.h"
#include "IO.h"
#include <Model.h>

namespace fpr
{
uint32_t        ModelLoader::mesh_index = 0;
ModelPrimitives ModelLoader::LoadModelAssimp(const char* file_name)
{
  //Load model data and parse it using assimp.
  std::string_view file_name_sv(file_name);
  Assimp::Importer importer;
  const aiScene*   scene = importer.ReadFile(file_name, USING_ASSIMP_DEFAULT_FLAGS);

  if(!scene)
    std::cout << "Failed to load scene:\t" << file_name << '\n';
  size_t          last_slash_pos = file_name_sv.rfind("/") + 1; //+1 to include the "/"
  std::string     file_directory(file_name_sv.substr(0, last_slash_pos));
  ModelPrimitives data;

  data.meshes.reserve(scene->mNumMeshes);
  //Iterate over the meshes in the model.
  for(size_t mesh = 0; mesh < scene->mNumMeshes; ++mesh)
  {
    std::vector<fpr::Vertex> mesh_vertices;
    std::vector<uint32_t>    mesh_indices;
    aiMesh*                  current_mesh = scene->mMeshes[mesh];

    aiMaterial* material      = scene->mMaterials[current_mesh->mMaterialIndex];
    bool        using_normals = current_mesh->HasNormals();

    //Potential materials to be used.
    aiString albedo_path;
    aiString metal;
    aiString ao;
    aiString normal;
    aiString bump;
    aiString roughness;
    

    //Output the  available materials, mostly for debugging  purposes.
    for(auto& [name, type] : ASSIMP_TEXTURE_TYPES)
    {
      aiString mat_name;
      if(material->GetTexture(type, 0, &mat_name) == aiReturn_SUCCESS)
        printf("%s\t %s\n", name, mat_name.C_Str());
    }

    //Store diffuse  map.
    material->GetTexture(aiTextureType_DIFFUSE, 0, &albedo_path);

    std::string full_albedo_path(file_directory);
    full_albedo_path.append(albedo_path.C_Str());

    //Store  primitves,  such as UVs, vertices, normals and tangents.
    for(size_t vert = 0; vert < current_mesh->mNumVertices; ++vert)
    {
      fpr::Vertex vertex;
      vertex.position.x = current_mesh->mVertices[vert].x;
      vertex.position.y = current_mesh->mVertices[vert].y;
      vertex.position.z = current_mesh->mVertices[vert].z;

      if(current_mesh->HasTextureCoords(0))
      {
        vertex.uv.x = current_mesh->mTextureCoords[0][vert].x;
        vertex.uv.y = current_mesh->mTextureCoords[0][vert].y;
      }

      if(using_normals)
      {
        vertex.normal.x = current_mesh->mNormals[vert].x;
        vertex.normal.y = current_mesh->mNormals[vert].y;
        vertex.normal.z = current_mesh->mNormals[vert].z;
      }
      if(current_mesh->HasTangentsAndBitangents())
      {
        vertex.tangent.x = current_mesh->mTangents[vert].x;
        vertex.tangent.y = current_mesh->mTangents[vert].y;
        vertex.tangent.z = current_mesh->mTangents[vert].z;
      }
      mesh_vertices.push_back(vertex);
    }

 
    for(size_t face = 0; face < current_mesh->mNumFaces; ++face)
    {
      aiFace* current_face = &current_mesh->mFaces[face];

      mesh_indices.push_back(current_face->mIndices[0]);
      mesh_indices.push_back(current_face->mIndices[1]);
      mesh_indices.push_back(current_face->mIndices[2]);
    }

    data.indices.insert(std::end(data.indices), std::begin(mesh_indices), std::end(mesh_indices));
    data.vertices.insert(std::end(data.vertices), std::begin(mesh_vertices), std::end(mesh_vertices));

    vk::DeviceSize index_offset  = data.indices.size() - mesh_indices.size();
    vk::DeviceSize vertex_offset = sizeof Vertex * data.vertices.size() - sizeof Vertex * mesh_vertices.size();

    data.meshes.emplace_back(
        mesh_index,
        (vk::DeviceSize)index_offset,
        (uint32_t)mesh_indices.size(),
        vertex_offset,
        (uint32_t)mesh_vertices.size(),
        full_albedo_path);
    mesh_index++;
  }
  return data;
}
} // namespace fpr