Mesh loading

This commit is contained in:
tovjemam 2025-08-06 20:21:16 +02:00
parent b8316238b4
commit 21fa4c6d6f
5 changed files with 120 additions and 19 deletions

View File

@ -1,8 +1,8 @@
cmake_minimum_required(VERSION 3.15)
project(PortalGame)
# Enable C++17
set(CMAKE_CXX_STANDARD 17)
# Enable C++20
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Add src directory
@ -12,8 +12,7 @@ add_executable(PortalGame
"src/app.cpp"
"src/gl.hpp"
"src/utils.hpp"
"src/assets/load_mesh.hpp"
"src/assets/load_mesh.cpp"
"src/assets/mesh.cpp"
"src/gfx/buffer_object.cpp"
"src/gfx/buffer_object.hpp"
"src/gfx/texture.cpp"

View File

@ -1,15 +0,0 @@
#pragma once
#include <memory>
#include <string>
#include "gfx/vertex_array.hpp"
namespace assets
{
std::shared_ptr<VertexArray> LoadMesh(const std::string& filename);
}

73
src/assets/mesh.cpp Normal file
View File

@ -0,0 +1,73 @@
#include "mesh.hpp"
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include <map>
std::shared_ptr<assets::Mesh> assets::Mesh::LoadFromFile(const std::string& filename)
{
std::ifstream file(filename, std::ios::binary);
if (!file.is_open())
{
throw std::runtime_error("Failed to open mesh file: " + filename);
}
std::vector<MeshVertex> verts;
std::vector<MeshTriangle> tris;
std::vector<MeshMaterialSlot> materials;
std::string line;
while (std::getline(file, line))
{
if (line.empty() || line[0] == '#') // Skip empty lines and comments
continue;
std::istringstream iss(line);
std::string command;
iss >> command;
if (command == "v") // Vertex
{
MeshVertex& vertex = verts.emplace_back();
iss >> vertex.pos.x >> vertex.pos.y >> vertex.pos.z;
iss >> vertex.normal.x >> vertex.normal.y >> vertex.normal.z;
iss >> vertex.uv.x >> vertex.uv.y;
iss >> vertex.lightmap_uv.x >> vertex.lightmap_uv.y;
}
else if (command == "m") // Material switch
{
if (materials.size() > 0)
{
MeshMaterialSlot& last_material = materials.back();
last_material.num_tris = tris.size() - last_material.first_tri;
}
MeshMaterialSlot& material = materials.emplace_back();
iss >> material.name;
material.first_tri = tris.size();
}
else if (command == "f") // Face
{
MeshTriangle& tri = tris.emplace_back();
iss >> tri.vert[0] >> tri.vert[1] >> tri.vert[2];
}
}
if (materials.size() > 0)
{
MeshMaterialSlot& last_material = materials.back();
last_material.num_tris = tris.size() - last_material.first_tri;
}
file.close();
if (verts.empty() || tris.empty())
{
throw std::runtime_error("Mesh file is empty or malformed: " + filename);
}
return std::make_shared<Mesh>(verts, tris, materials);
}

44
src/assets/mesh.hpp Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include <memory>
#include <string>
#include <span>
#include <glm/glm.hpp>
#include "gfx/vertex_array.hpp"
#include "gfx/texture.hpp"
namespace assets
{
struct MeshVertex
{
glm::vec3 pos;
glm::vec3 normal;
glm::vec2 uv;
glm::vec2 lightmap_uv;
};
struct MeshTriangle
{
uint32_t vert[3];
};
struct MeshMaterialSlot
{
std::string name;
std::shared_ptr<gfx::Texture> texture;
size_t first_tri = 0;
size_t num_tris = 0;
};
class Mesh
{
gfx::VertexArray va_;
std::vector<MeshMaterialSlot> materials_;
public:
Mesh(std::span<MeshVertex> verts, std::span<MeshTriangle> tris, std::span<MeshMaterialSlot> materials);
static std::shared_ptr<Mesh> LoadFromFile(const std::string& filename);
};
}