Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions include/renderer/Mesh.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ struct Vertex {
glm::vec3 m_position;
glm::vec3 m_normal;
glm::vec2 m_tex_coords;

// first byte diffuse
// second byte opacity
uint32_t texture_indices;
};

struct AABB {
Expand All @@ -20,25 +24,28 @@ struct AABB {
AABB merge(AABB const&);
};

struct IntermediateMesh {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
std::vector<Texture const*> textures;
AABB aabb;

bool merge(IntermediateMesh const&);
};

class Mesh {
public:
std::vector<Vertex> m_vertices;
std::vector<unsigned int> m_indices;
Texture const* m_texture_diffuse;
Texture const* m_texture_opacity;
std::vector<Texture const*> textures;
AABB aabb;

Mesh(std::vector<Vertex> vertices,
std::vector<unsigned int> indices,
Texture const* texture_diffuse,
Texture const* texture_opacity,
AABB);
Mesh(IntermediateMesh);

void draw() const;
void draw(ViewingMode) const;
[[nodiscard]] bool is_fully_loaded() const;
void setup_mesh();
void setup_mesh(std::vector<Vertex> const& vertices, std::vector<unsigned int> const& indices);

private:
unsigned int m_vao{0}, m_vbo{0}, m_ebo{0};
unsigned int m_indices_size;
};
2 changes: 1 addition & 1 deletion include/renderer/Shader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ struct UniformLocations {
int projection{-1};

// Fragment
int texture_diffuse{-1};
int textures[16]{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
int texture_opacity{-1};
int light_direction{-1};
int light_color{-1};
Expand Down
40 changes: 17 additions & 23 deletions src/core/ModelLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#include <glad/glad.h>
#include <glm/gtc/quaternion.hpp>
#include <iostream>
#include <map>
#include <vector>

glm::vec3 ai_to_glm_vec(aiVector3D vector)
Expand Down Expand Up @@ -145,7 +144,7 @@ Texture const* load_mask_texture(aiMaterial* mat, std::filesystem::path director
}
}

Mesh process_mesh(aiMesh* mesh, aiScene const* scene, std::filesystem::path directory)
IntermediateMesh process_mesh(aiMesh* mesh, aiScene const* scene, std::filesystem::path directory)
{
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
Expand Down Expand Up @@ -176,6 +175,9 @@ Mesh process_mesh(aiMesh* mesh, aiScene const* scene, std::filesystem::path dire
vertex.m_tex_coords = {0.0f, 0.0f};
}

// diffuse: 0; opacity: 1
vertex.texture_indices = 0x00010000;

vertices.push_back(vertex);

// if you want to add more attributes do it here
Expand All @@ -191,25 +193,26 @@ Mesh process_mesh(aiMesh* mesh, aiScene const* scene, std::filesystem::path dire
// assign materials if any
auto material = scene->mMaterials[mesh->mMaterialIndex];

std::vector<Texture const*> textures;

auto texture_diffuse = load_material_texture(material, aiTextureType_DIFFUSE, directory);
if (!texture_diffuse) {
texture_diffuse = Project::get_current()->fallback_texture();
}
textures.push_back(texture_diffuse);

// TODO: Find mask texture
// Each texture has a <texture name>.meta file that includes a guid
// And each material has a list of linked textures that include a base and mask texture guid
auto texture_opacity = load_mask_texture(material, directory);
if (!texture_opacity) {
texture_opacity = Project::get_current()->white_texture();
}
textures.push_back(texture_opacity);

auto aabb = AABB{
.min = ai_to_glm_vec(mesh->mAABB.mMin),
.max = ai_to_glm_vec(mesh->mAABB.mMax),
};

return Mesh{vertices, indices, texture_diffuse, texture_opacity, aabb};
return IntermediateMesh{vertices, indices, textures, aabb};
}

Node process_node(aiNode* node, aiScene const* scene, std::filesystem::path directory, NodeLocation parent_location)
Expand All @@ -230,13 +233,13 @@ Node process_node(aiNode* node, aiScene const* scene, std::filesystem::path dire
auto location = NodeLocation::file(parent_location.file_path, parent_location.node_path / name);
auto new_node = Node::create(name, new_transform, location);

std::map<std::pair<Texture const*, Texture const*>, Mesh> merged_meshes;
std::vector<IntermediateMesh> merged_meshes;

// This messy code transforms the vertices and the positions in such a way that the mesh vertices are built around the object center.
// This ensures that the gizmos aren't diplayed somewhere far away.
// It also merges meshes with identical textures to improve performance.
// It also merges meshes to improve performance.

// 1. Load all meshes and compute the node's AABB
// 1. Load and merge all meshes and compute the node's AABB
std::optional<AABB> aabb;
for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
Expand All @@ -247,16 +250,8 @@ Node process_node(aiNode* node, aiScene const* scene, std::filesystem::path dire
aabb = aabb->merge(new_mesh.aabb);
}

auto key = std::make_pair(new_mesh.m_texture_diffuse, new_mesh.m_texture_opacity);
if (merged_meshes.contains(key)) {
auto& merged_mesh = merged_meshes.at(key);
auto start_index = merged_mesh.m_vertices.size();
for (auto index : new_mesh.m_indices) {
merged_mesh.m_indices.push_back(start_index + index);
}
merged_mesh.m_vertices.insert(merged_mesh.m_vertices.end(), new_mesh.m_vertices.begin(), new_mesh.m_vertices.end());
} else {
merged_meshes.emplace(key, std::move(new_mesh));
if (merged_meshes.size() == 0 || !merged_meshes.back().merge(new_mesh)) {
merged_meshes.push_back(new_mesh);
}
}

Expand All @@ -271,14 +266,13 @@ Node process_node(aiNode* node, aiScene const* scene, std::filesystem::path dire
}

// 3. Move vertices, setup mesh buffers and add the meshes to the node
for (auto& [_, mesh] : merged_meshes) {
for (auto& vertex : mesh.m_vertices) {
for (auto& mesh : merged_meshes) {
for (auto& vertex : mesh.vertices) {
vertex.m_position -= center;
}
mesh.aabb.min -= center;
mesh.aabb.max -= center;
mesh.setup_mesh();
new_node.meshes.push_back(std::move(mesh));
new_node.meshes.push_back(mesh);
}

// 4. Load and move the child nodes
Expand Down
5 changes: 3 additions & 2 deletions src/renderer/Camera.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,9 @@ void Camera::draw_outline(Framebuffer const& framebuffer, InstancedNode const& n
Shader::albedo.set_uniform(Shader::albedo.uniform_locations.gamma, 1.0f);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, project->white_texture()->id);
Shader::albedo.set_uniform(Shader::albedo.uniform_locations.texture_diffuse, 0);
Shader::albedo.set_uniform(Shader::albedo.uniform_locations.texture_opacity, 0);
for (std::size_t i = 0; i < sizeof(Shader::albedo.uniform_locations.textures) / sizeof(Shader::albedo.uniform_locations.textures[0]); ++i) {
Shader::albedo.set_uniform(Shader::albedo.uniform_locations.textures[i], 0);
}

node.traverse([&](auto transform_matrix, auto const& node_data) {
Shader::albedo.set_uniform(Shader::albedo.uniform_locations.model, transform_matrix);
Expand Down
95 changes: 73 additions & 22 deletions src/renderer/Mesh.cpp
Original file line number Diff line number Diff line change
@@ -1,42 +1,85 @@
#include "renderer/Mesh.hpp"

#include "core/Project.hpp"
#include <iostream>
#include <map>

Mesh::Mesh(std::vector<Vertex> vertices, std::vector<unsigned int> indices, Texture const* texture_diffuse, Texture const* texture_opacity, AABB aabb)
: m_vertices(vertices)
, m_indices(indices)
, m_texture_diffuse(texture_diffuse)
, m_texture_opacity(texture_opacity)
, aabb(aabb)
{ }
bool IntermediateMesh::merge(IntermediateMesh const& other)
{
std::size_t new_textures_count = 0;
for (auto other_texture : other.textures) {
auto found_it = std::find(textures.begin(), textures.end(), other_texture);
if (found_it == textures.end()) {
++new_textures_count;
}
}

if (textures.size() + new_textures_count > 16) {
return false;
}

std::map<std::size_t, std::size_t> texture_mapping;
for (std::size_t i = 0; auto other_texture : other.textures) {
auto found_it = std::find(textures.begin(), textures.end(), other_texture);
if (found_it == textures.end()) {
texture_mapping[i] = textures.size();
textures.push_back(other_texture);
} else {
texture_mapping[i] = found_it - textures.begin();
}
++i;
}

for (auto vertex : other.vertices) {
auto diffuse_index = texture_mapping[vertex.texture_indices >> 24];
auto opacity_index = texture_mapping[(vertex.texture_indices >> 16) & 0xff];
vertex.texture_indices = (diffuse_index << 24) | (opacity_index << 16);
vertices.push_back(vertex);
}

auto index_offset = indices.size();
for (auto index : other.indices) {
indices.push_back(index + index_offset);
}

aabb = aabb.merge(other.aabb);
return true;
}

Mesh::Mesh(IntermediateMesh mesh)
{
m_indices_size = mesh.indices.size();
textures = mesh.textures;

setup_mesh(mesh.vertices, mesh.indices);
}

void Mesh::draw() const
{
glBindVertexArray(m_vao);
glDrawElements(GL_TRIANGLES, m_indices.size(), GL_UNSIGNED_INT, nullptr);
glDrawElements(GL_TRIANGLES, m_indices_size, GL_UNSIGNED_INT, nullptr);
}

void Mesh::draw(ViewingMode mode) const
{
auto const& shader = Shader::get_shader_for_mode(mode);
auto diffuse_texture_id = mode == ViewingMode::SOLID ? Project::get_current()->fallback_texture()->id : m_texture_diffuse->id;

// set diffuse texture
glActiveTexture(GL_TEXTURE0);
shader.set_uniform(shader.uniform_locations.texture_diffuse, 0);
glBindTexture(GL_TEXTURE_2D, diffuse_texture_id);
for (std::size_t i = 0; auto const& texture : textures) {
auto id = mode == ViewingMode::SOLID ? Project::get_current()->fallback_texture()->id : texture->id;

glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(GL_TEXTURE_2D, id);
shader.set_uniform(shader.uniform_locations.textures[i], static_cast<int>(i));

// set opacity texture
glActiveTexture(GL_TEXTURE1);
shader.set_uniform(shader.uniform_locations.texture_opacity, 1);
glBindTexture(GL_TEXTURE_2D, m_texture_opacity->id);
++i;
}

// set active
glBindVertexArray(m_vao);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(m_indices.size()), GL_UNSIGNED_INT, nullptr);
glDrawElements(GL_TRIANGLES, static_cast<unsigned int>(m_indices_size), GL_UNSIGNED_INT, nullptr);
}

void Mesh::setup_mesh()
void Mesh::setup_mesh(std::vector<Vertex> const& vertices, std::vector<unsigned int> const& indices)
{
if (m_vao != 0) {
return;
Expand All @@ -48,10 +91,10 @@ void Mesh::setup_mesh()

glBindVertexArray(m_vao);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
glBufferData(GL_ARRAY_BUFFER, m_vertices.size() * sizeof(Vertex), &m_vertices[0], GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_indices.size() * sizeof(unsigned int), &m_indices[0], GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), &indices[0], GL_STATIC_DRAW);

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(0);
Expand All @@ -61,11 +104,19 @@ void Mesh::setup_mesh()
// vertex texture coords
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, m_tex_coords));
glEnableVertexAttribArray(2);
// texture index
glVertexAttribIPointer(3, 1, GL_UNSIGNED_INT, sizeof(Vertex), (void*)offsetof(Vertex, texture_indices));
glEnableVertexAttribArray(3);
}

bool Mesh::is_fully_loaded() const
{
return m_texture_diffuse->is_loaded;
for (auto const& texture : textures) {
if (!texture->is_loaded) {
return false;
}
}
return true;
}

AABB AABB::merge(AABB const& other)
Expand Down
Loading