added monitors, improved scene

This commit is contained in:
Jay Robson 2024-01-24 18:34:04 +11:00
parent 6145059116
commit 7a2164c169
23 changed files with 286 additions and 219 deletions

View File

@ -1,5 +1,4 @@
# Credits
- [Monitor - SCP](https://skfb.ly/6RKYR) by Maxime66410 is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).
- [Potted House Plants](https://skfb.ly/opQN8) by FacultyManBruce is licensed under Creative Commons Attribution (http://creativecommons.org/licenses/by/4.0/).

View File

@ -3,7 +3,8 @@
#include <GLFW/glfw3.h>
#include "camera.hpp"
#include "keyboard.hpp"
#include "input/keyboard.hpp"
#include "../math.hpp"
#include <iostream>
#include <glm/matrix.hpp>
@ -15,11 +16,12 @@ using namespace sim::graphics;
static double yaw = 0, pitch = 0;
static glm::vec<3, double> pos(0, 0, 2);
static glm::vec<3, double> velocity(0);
static glm::mat4 camera_mat;
void camera::rotate(double y, double p)
{
yaw -= y * 0.05;
pitch += p * 0.05;
yaw += y * 0.05;
pitch -= p * 0.05;
if(pitch < 0) pitch = 0;
if(pitch > 180) pitch = 180;
@ -42,9 +44,9 @@ void camera::update()
if(keyboard::is_pressed(GLFW_KEY_S))
off.y -= 1;
if(keyboard::is_pressed(GLFW_KEY_A))
off.x += 1;
if(keyboard::is_pressed(GLFW_KEY_D))
off.x -= 1;
if(keyboard::is_pressed(GLFW_KEY_D))
off.x += 1;
if(keyboard::is_pressed(GLFW_KEY_LEFT_SHIFT))
m *= 1.5;
if(off.x != 0 || off.y != 0)
@ -74,6 +76,7 @@ void camera::update()
else
{
velocity.z = 0;
pos.z = 1.6;
}
}
@ -91,17 +94,18 @@ void camera::update()
velocity.y = 0;
pos += velocity;
velocity *= glm::vec<3, double>(on_ground ? 0.9 : 0.9999);
velocity *= glm::vec<3, double>(on_ground ? 0.9 : 0.999);
camera_mat = glm::mat4(1);
camera_mat = glm::rotate(camera_mat, (float)glm::radians(-pitch), glm::vec3(1, 0, 0));
camera_mat = glm::rotate(camera_mat, (float)glm::radians(yaw), glm::vec3(0, 0, 1));
camera_mat = glm::translate(camera_mat, glm::vec3(-pos.x, -pos.y, -pos.z));
std::cout << "at: " << pos << "\n";
}
glm::mat4 camera::get_model_matrix()
glm::mat4 camera::get_matrix()
{
glm::mat4 mat(1);
mat = glm::rotate(mat, (float)glm::radians(pitch), glm::vec3(1, 0, 0));
mat = glm::rotate(mat, (float)glm::radians(yaw), glm::vec3(0, 0, 1));
mat = glm::translate(mat, glm::vec3(pos.x, pos.y, pos.z));
return mat;
return camera_mat;
}

View File

@ -7,7 +7,7 @@
namespace sim::graphics::camera
{
glm::mat4 get_model_matrix();
glm::mat4 get_matrix();
void rotate(double pitch, double yaw);
void move(double x, double y, double z);
void update();

View File

@ -1,72 +0,0 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <glm/vec2.hpp>
#include <iostream>
#include "font.hpp"
using namespace sim::graphics;
font::character font::chars[128];
void font::init()
{
FT_Library ft;
FT_Face face;
if(FT_Init_FreeType(&ft))
{
std::cout << "Error: failed to init freetype\n";
return;
}
if(FT_New_Face(ft, "/usr/share/fonts/noto/NotoSans-Regular.ttf", 0, &face))
{
std::cout << "Error: failed to load freetype font\n";
return;
}
FT_Set_Pixel_Sizes(face, 0, 1024);
GLuint texids[128];
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glCreateTextures(GL_TEXTURE_2D, 128, texids);
for(int i = 0; i < 128; i++)
{
if(FT_Load_Char(face, (char)i, FT_LOAD_RENDER))
{
std::cout << "Error: failed to load glyph " << i << "\n";
}
character& c = chars[i];
c.advance = face->glyph->advance.x;
c.size = {face->glyph->bitmap.width, face->glyph->bitmap.rows};
c.bearing = {face->glyph->bitmap_left, face->glyph->bitmap_top};
if(c.size.x == 0 || c.size.y == 0)
{
c.handle = 0;
continue;
}
glTextureStorage2D(texids[i], 1, GL_R8, c.size.x, c.size.y);
glTextureSubImage2D(texids[i], 0, 0, 0, c.size.x, c.size.y, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTextureParameteri(texids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(texids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
c.handle = glGetTextureHandleARB(texids[i]);
glMakeTextureHandleResidentARB(c.handle);
chars[i] = c;
}
}

View File

@ -1,20 +0,0 @@
#pragma once
namespace sim::graphics::font
{
struct character
{
unsigned long handle;
long advance;
glm::ivec2 size;
glm::ivec2 bearing;
};
void init();
extern character chars[128];
};

View File

@ -5,9 +5,9 @@
#include <unordered_map>
#include "keyboard.hpp"
#include "window.hpp"
#include "resize.hpp"
#include "camera.hpp"
#include "../window.hpp"
#include "../resize.hpp"
#include "../camera.hpp"
using namespace sim::graphics;

View File

@ -3,8 +3,8 @@
#include <GLFW/glfw3.h>
#include "mouse.hpp"
#include "window.hpp"
#include "camera.hpp"
#include "../window.hpp"
#include "../camera.hpp"
using namespace sim::graphics;

View File

@ -4,7 +4,7 @@
#include <assimp/Importer.hpp>
#include "shader.hpp"
#include "../shader.hpp"
#include "arrays.hpp"
#include "font.hpp"
@ -32,8 +32,5 @@ void arrays::vertex_attrib_pointers()
glVertexAttribPointer(3, 3, GL_FLOAT, false, sizeof(v), ptr_diff(&v.normal, &v));
glEnableVertexAttribArray(3);
glVertexAttribPointer(4, 1, GL_FLOAT, false, sizeof(v), ptr_diff(&v.do_tex, &v));
glEnableVertexAttribArray(4);
}

View File

@ -13,10 +13,6 @@ struct vertex
glm::vec2 texpos = {0, 0};
glm::vec3 pos = {0, 0, 0};
glm::vec3 normal = {0, 0, 0};
float do_tex = 0;
vertex() { }
vertex(unsigned long texid, glm::vec2 texpos, glm::vec3 pos) : texid(texid), texpos(texpos), pos(pos) { }
};
void vertex_attrib_pointers();

141
src/graphics/mesh/font.cpp Normal file
View File

@ -0,0 +1,141 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <ft2build.h>
#include FT_FREETYPE_H
#include <glm/vec2.hpp>
#include <iostream>
#include <vector>
#include "arrays.hpp"
#include "font.hpp"
using namespace sim::graphics;
struct character
{
unsigned long handle;
float advance;
glm::vec2 size;
glm::vec2 bearing;
};
static character chars[128];
void font::init()
{
FT_Library ft;
FT_Face face;
if(FT_Init_FreeType(&ft))
{
std::cout << "Error: failed to init freetype\n";
return;
}
if(FT_New_Face(ft, "../assets/font/DroidSans.ttf", 0, &face))
{
std::cout << "Error: failed to load freetype font\n";
return;
}
int size = 1024;
float m = 1.0f / size;
FT_Set_Pixel_Sizes(face, 0, size);
GLuint texids[128];
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
for(int i = 0; i < 128; i++)
{
if(FT_Load_Char(face, (char)i, FT_LOAD_RENDER))
{
std::cout << "Error: failed to load glyph " << i << "\n";
}
int width = face->glyph->bitmap.width;
int height = face->glyph->bitmap.rows;
int offx = face->glyph->bitmap_left;
int offy = face->glyph->bitmap_top;
character& c = chars[i];
c.advance = face->glyph->advance.x * m / 64.0;
c.size = {width * m, height * m};
c.bearing = {offx * m, offy * m};
if(c.size.x == 0 || c.size.y == 0)
{
c.handle = 0;
continue;
}
glCreateTextures(GL_TEXTURE_2D, 1, &texids[i]);
glTextureStorage2D(texids[i], 1, GL_R8, width, height);
glTextureSubImage2D(texids[i], 0, 0, 0, width, height, GL_RED, GL_UNSIGNED_BYTE, face->glyph->bitmap.buffer);
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(texids[i], GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTextureParameteri(texids[i], GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTextureParameteri(texids[i], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
c.handle = glGetTextureHandleARB(texids[i]);
glMakeTextureHandleResidentARB(c.handle);
chars[i] = c;
}
}
void font::generate(mesh& m, const char* text, double size)
{
std::vector<arrays::vertex> vertices;
std::vector<unsigned int> indices;
float x = 0, y = size;
unsigned int at = 0;
for(unsigned int i = 0; text[i] != '\0'; i++)
{
char c = text[i];
character ch = chars[c];
if(c == '\n')
{
x = 0;
y += size;
continue;
}
if(ch.handle == 0)
{
x += ch.advance * size;
continue;
}
unsigned int index[6] = {
at, at + 1, at + 3,
at, at + 3, at + 2
};
float sx = x + ch.bearing.x * size;
float sy = y - ch.bearing.y * size;
float ex = sx + ch.size.x * size;
float ey = sy + ch.size.y * size;
vertices.push_back(arrays::vertex(ch.handle, {0, 0}, {sx, sy, 0}, {0, 0, -1}));
vertices.push_back(arrays::vertex(ch.handle, {0, 1}, {sx, ey, 0}, {0, 0, -1}));
vertices.push_back(arrays::vertex(ch.handle, {1, 0}, {ex, sy, 0}, {0, 0, -1}));
vertices.push_back(arrays::vertex(ch.handle, {1, 1}, {ex, ey, 0}, {0, 0, -1}));
indices.insert(indices.end(), &index[0], &index[6]);
at += 4;
x += ch.advance * size;
}
m.set_vertices(&vertices[0], vertices.size(), GL_DYNAMIC_DRAW);
m.set_indices(&indices[0], indices.size(), GL_DYNAMIC_DRAW);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "mesh.hpp"
#include <string>
namespace sim::graphics::font
{
void init();
void generate(mesh& m, const char* text, double size);
};

View File

@ -4,19 +4,25 @@
#include "mesh.hpp"
#include "arrays.hpp"
#include <iostream>
#include "../shader.hpp"
#include "../camera.hpp"
using namespace sim::graphics;
mesh::mesh()
constexpr static void init(mesh* m)
{
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ebo);
if(m->vao != 0)
{
return;
}
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glGenVertexArrays(1, &m->vao);
glGenBuffers(1, &m->vbo);
glGenBuffers(1, &m->ebo);
glBindVertexArray(m->vao);
glBindBuffer(GL_ARRAY_BUFFER, m->vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m->ebo);
arrays::vertex_attrib_pointers();
}
@ -27,6 +33,9 @@ mesh::mesh(mesh&& o)
ebo = o.ebo;
vao = o.vao;
size = o.size;
colour_matrix = o.colour_matrix;
model_matrix = o.model_matrix;
o.vbo = 0;
o.ebo = 0;
o.vao = 0;
@ -50,12 +59,17 @@ void mesh::set_indices(const unsigned int* data, size_t size, int mode)
this->size = size;
}
void mesh::bind() const
void mesh::bind()
{
init(this);
glm::mat4 m = camera::get_matrix() * model_matrix;
glUniformMatrix4fv(shader::gl_model, 1, false, &m[0][0]);
glUniformMatrix4fv(shader::gl_tex_mat, 1, false, &colour_matrix[0][0]);
glBindVertexArray(vao);
}
void mesh::render() const
void mesh::render()
{
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
}

View File

@ -1,7 +1,10 @@
#pragma once
#include <string>
#include "arrays.hpp"
#include <glm/matrix.hpp>
namespace sim::graphics
{
@ -10,15 +13,20 @@ struct mesh
{
unsigned int vao = 0, vbo = 0, ebo = 0, size = 0;
mesh();
glm::mat4 model_matrix {1.0f};
glm::mat4 colour_matrix {1.0f};
constexpr mesh() { }
mesh(mesh&& o);
mesh(const mesh& o) = delete;
~mesh();
void bind() const;
void bind();
void set_vertices(const arrays::vertex* data, size_t size, int mode);
void set_indices(const unsigned int* data, size_t size, int mode);
void render() const;
void load_model(std::string base, std::string path);
void render();
};
};

View File

@ -10,7 +10,6 @@
#include <vector>
#include "mesh.hpp"
#include "model.hpp"
#include "arrays.hpp"
#include "texture.hpp"
@ -23,7 +22,6 @@ struct proc_state
std::string base;
std::vector<arrays::vertex> vertices;
std::vector<unsigned int> indices;
glm::vec<3, double> pos;
};
static unsigned int proc_texture(const proc_state& state, aiMaterial* mat, aiTextureType type)
@ -42,7 +40,7 @@ static unsigned int proc_texture(const proc_state& state, aiMaterial* mat, aiTex
return texture::load(state.base + "/" + filename);
}
static void proc_mesh(proc_state& state, std::vector<mesh>& meshes, aiMesh* mesh, const aiScene* scene)
static void proc_mesh(proc_state& state, aiMesh* mesh, const aiScene* scene)
{
aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
unsigned int texid = proc_texture(state, material, aiTextureType_DIFFUSE);
@ -51,19 +49,21 @@ static void proc_mesh(proc_state& state, std::vector<mesh>& meshes, aiMesh* mesh
for(unsigned int i = 0; i < mesh->mNumVertices; i++)
{
arrays::vertex vertex;
auto [x, y, z] = mesh->mVertices[i];
vertex.pos = {y, x, -z};
vertex.texid = texid;
vertex.pos = state.pos + glm::vec<3, double>(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z);
if(mesh->HasNormals())
{
vertex.normal = {mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z};
auto [x, y, z] = mesh->mNormals[i];
vertex.normal = {y, x, -z};
}
if(mesh->mTextureCoords[0])
{
vertex.texpos = {mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y};
vertex.do_tex = 1;
auto [x, y, z] = mesh->mTextureCoords[0][i];
vertex.texpos = {x, y};
}
state.vertices.push_back(vertex);
@ -82,41 +82,30 @@ static void proc_mesh(proc_state& state, std::vector<mesh>& meshes, aiMesh* mesh
state.offset += mesh->mNumVertices;
}
static void proc_node(proc_state& state, std::vector<mesh>& meshes, aiNode* node, const aiScene* scene)
static void proc_node(proc_state& state, aiNode* node, const aiScene* scene)
{
for(size_t i = 0; i < node->mNumMeshes; i++)
{
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
proc_mesh(state, meshes, mesh, scene);
proc_mesh(state, mesh, scene);
}
for(size_t i = 0; i < node->mNumChildren; i++)
{
proc_node(state, meshes, node->mChildren[i], scene);
proc_node(state, node->mChildren[i], scene);
}
}
void model::load(std::string base, std::string filename, glm::vec<3, double> pos)
void mesh::load_model(std::string base, std::string filename)
{
proc_state state {.base = base, .pos = pos};
proc_state state {.base = base};
std::string path = base + "/" + filename;
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path.c_str(), aiProcess_Triangulate | aiProcess_FlipUVs);
proc_node(state, meshes, scene->mRootNode, scene);
proc_node(state, scene->mRootNode, scene);
sim::graphics::mesh m;
m.set_vertices(&state.vertices[0], state.vertices.size(), GL_STATIC_DRAW);
m.set_indices(&state.indices[0], state.indices.size(), GL_STATIC_DRAW);
meshes.push_back(std::move(m));
}
void model::render() const
{
for(const mesh& m : meshes)
{
m.bind();
m.render();
}
set_vertices(&state.vertices[0], state.vertices.size(), GL_STATIC_DRAW);
set_indices(&state.indices[0], state.indices.size(), GL_STATIC_DRAW);
}

View File

@ -1,23 +0,0 @@
#pragma once
#include "mesh.hpp"
#include <glm/vec3.hpp>
#include <vector>
#include <string>
namespace sim::graphics
{
struct model
{
std::vector<mesh> meshes;
void load(std::string base, std::string path, glm::vec<3, double> offset);
void load(std::string base, std::string path) { load(base, path, {0, 0, 0}); }
void render() const;
};
};

View File

@ -17,12 +17,10 @@ layout (location = 0) in sampler2D aTex;
layout (location = 1) in vec2 aTexPos;
layout (location = 2) in vec3 aPos;
layout (location = 3) in vec3 aNormal;
layout (location = 4) in float aDoTex;
uniform mat4 model;
uniform mat4 projection;
out float do_tex;
out float brightness;
out flat sampler2D tex;
out vec2 texPos;
@ -33,7 +31,6 @@ void main()
vec3 cNormal = vec3(0.f, 0.f, 1.f) * mat3(model);
brightness = dot(normalize(aNormal), normalize(cNormal)) * 0.25f + 0.75f;
do_tex = aDoTex;
gl_Position = projection * pos;
texPos = aTexPos;
@ -46,7 +43,6 @@ static const char* FRAGMENT_SHADER = R"(
#version 460 core
#extension GL_ARB_bindless_texture : require
in float do_tex;
in float brightness;
in flat sampler2D tex;
in vec2 texPos;
@ -57,8 +53,10 @@ uniform mat4 tex_mat;
void main()
{
vec4 texdata = (do_tex > 0.5f) ? texture2D(tex, texPos) : vec4(1);
vec4 texdata = texture2D(tex, texPos);
FragColour = tex_mat * texdata * vec4(vec3(brightness), 1);
if(FragColour.a == 0) discard;
}
)";
@ -66,7 +64,6 @@ void main()
static unsigned int prog_id;
int shader::gl_tex_mat;
int shader::gl_do_tex;
int shader::gl_model;
int shader::gl_projection;
@ -102,7 +99,6 @@ unsigned int shader::init_program()
}
gl_tex_mat = glGetUniformLocation(prog_id, "tex_mat");
gl_do_tex = glGetUniformLocation(prog_id, "do_tex");
gl_model = glGetUniformLocation(prog_id, "model");
gl_projection = glGetUniformLocation(prog_id, "projection");

View File

@ -5,7 +5,6 @@ namespace sim::graphics::shader
{
extern int gl_tex_mat;
extern int gl_do_tex;
extern int gl_model;
extern int gl_projection;

View File

@ -8,21 +8,21 @@
#include <iostream>
#include "model.hpp"
#include "arrays.hpp"
#include "keyboard.hpp"
#include "mouse.hpp"
#include "mesh/mesh.hpp"
#include "mesh/arrays.hpp"
#include "input/keyboard.hpp"
#include "input/mouse.hpp"
#include "camera.hpp"
#include "resize.hpp"
#include "window.hpp"
#include "shader.hpp"
#include "font.hpp"
#include "mesh/font.hpp"
using namespace sim::graphics;
static GLFWwindow* win;
static bool win_should_close = false;
static model Model;
static mesh MeshScene, MeshText;
void GLAPIENTRY cb_debug_message(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam)
{
@ -44,6 +44,7 @@ void window::create()
win = glfwCreateWindow(800, 600, "FastNuclearSim", nullptr, nullptr);
glfwMakeContextCurrent(win);
glfwSwapInterval(1);
GLenum err = glewInit();
@ -70,43 +71,46 @@ void window::create()
shader::init_program();
Model.load("../assets/scene", "scene.obj");
Model.load("../assets/AllPlants", "Plant3.obj", {2.5, 3.5, 0});
Model.load("../assets/AllPlants", "Plant1.obj", {-2.5, -3.5, 0});
Model.load("../assets/AllPlants", "Plant4.obj", {2, -3, 0});
Model.load("../assets/AllPlants", "Plant5.obj", {-2, 3, 0});
Model.load("../assets/monitor-scp", "Monitor.obj", {-3, 0, -2});
MeshScene.bind();
MeshScene.load_model("../assets", "scene.obj");
glm::mat4 mat = glm::mat4(1);
mat = glm::translate(mat, glm::vec3(-2.949, -1.7778, 3));
mat = glm::rotate(mat, glm::radians<float>(-90), glm::vec3(1, 0, 0));
mat = glm::rotate(mat, glm::radians<float>(-90), glm::vec3(0, 1, 0));
MeshText.model_matrix = mat;
MeshText.colour_matrix = {
1, 0, 0, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0
};
glViewport(0, 0, 800, 600);
}
void window::loop()
{
MeshText.bind();
font::generate(MeshText, "Hello, World!\nThis is cool!\n=)", 0.2);
glClearColor(0, 0, 0, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glm::mat4 mat_colour = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
};
camera::update();
glm::mat4 mat_model = camera::get_model_matrix();
double mouse_x, mouse_y;
mouse::get(mouse_x, mouse_y);
glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), (float)resize::get_aspect(), 0.01f, 20.f);
glUniformMatrix4fv(shader::gl_tex_mat, 1, false, &mat_colour[0][0]);
glm::mat4 mat_projection = glm::perspective(glm::radians(90.0f), 1.0f, 0.01f, 20.f);
glUniformMatrix4fv(shader::gl_projection, 1, false, &mat_projection[0][0]);
glUniformMatrix4fv(shader::gl_model, 1, false, &mat_model[0][0]);
glUniform1i(shader::gl_do_tex, 0);
Model.render();
MeshScene.bind();
MeshScene.render();
MeshText.bind();
MeshText.render();
glfwSwapBuffers(win);
glfwPollEvents();

20
src/math.hpp Normal file
View File

@ -0,0 +1,20 @@
#pragma once
#include <glm/matrix.hpp>
#include <ostream>
template <int N, typename T>
std::ostream& operator<<(std::ostream& o, const glm::vec<N, T>& v)
{
o << "{";
for(int i = 0; i < N - 1; i++)
{
o << v[i] << ", ";
}
o << v[N - 1] << "}";
return o;
}